#include <stdio.h>
int main(void) {
printf("Hello World\n");
return 0;
}
We're lazy! We don't want to declare the printf'stdio.h'
Specifically, the #includestdio.h #include
['A','B','C','\0']When you write a string literal "ABC" char * ptr
char *ptr = "ABC"
Some common ways to initialize a string include:
char *str = "ABC";
char str[] = "ABC";
char str[]={'A','B','C','\0'};
int *ptr1;
char *ptr2;
Due to C's grammar, an int* int* ptr3, ptr4;
Will only declare *ptr3* int* ptr3, ptr4;
int *ptrptr0x1000*ptr*ptr = 0; // Writes some memory.
What C will do is take the type of the pointer which is an int sizeof(int) 0x10000x10010x1002 0x1003
char *ptr = "Hello"; // ptr holds the memory location of 'H'
ptr += 2; //ptr now points to the first'l'
If an int is 4 bytes then ptr+1 points to 4 bytes after whatever ptr is pointing at.
char *ptr = "ABCDEFGH";
int *bna = (int *) ptr;
bna +=1; // Would cause iterate by one integer space (i.e 4 bytes on some systems)
ptr = (char *) bna;
printf("%s", ptr);
/* Notice how only 'EFGH' is printed. Why is that? Well as mentioned above, when performing
'bna
+=1' we are increasing the **integer** pointer by 1, (translates to 4 bytes on most
systems) which
is equivalent to 4 characters (each character is only 1 byte)*/
return 0;
Because pointer arithmetic in C is always automatically scaled by the size of the type that is pointed to, you can't perform pointer arithmetic on void pointers.
You can think of pointer arithmetic in C as essentially doing the following
If I want to do
int *ptr1 = ...;
int *offset = ptr1 + 4;
Thinkint *ptr1 = ...;
char *temp_ptr1 = (char*) ptr1;
int *offset = (int*)(temp_ptr1 + sizeof(int)*4);
To get the value. Every time you do pointer arithmetic, take a deep breath and make sure that you
are shifting over the number of bytes you think you are shifting over.void *give_me_space = malloc(10);
char *string = give_me_space;
This does not require a cast because C automatically promotes void* to its appropriate
type.Note:
gcc and clang are not total ISO-C compliant, meaning that they will let you do arithmetic on a void pointer. They will treat it as a char pointer but do not do this because it may not work with all compilers!
printfwrite printf printf write
printfprintf write printf
int num1 = 10;
printf("%d", num1); //prints num1
Example of integer pointer:
int *ptr = (int *) malloc(sizeof(int));
*ptr = 10;
printf("%p\n", ptr); //prints the address pointed to by the pointer
printf("%p\n", &ptr); /*prints the address of pointer -- extremely useful
when dealing with double pointers*/
printf("%d", *ptr); //prints the integer content of ptr
return 0;
Strings as Pointers & Arrays @ BU./program > output.txt
#To read the contents of the file,
cat output.txt
More complicated way: close(1) and then use open to re-open the file descriptor. See [[http://cs-
education.github.io/sys/#chapter/0/section/3/activity/0]]char ary[] = "Hello";
char *ptr = "Hello";
Example
The array name points to the first byte of the array. Both ary ptr
char ary[] = "Hello";
char *ptr = "Hello";
// Print out address and contents
printf("%p : %s\n", ary, ary);
printf("%p : %s\n", ptr, ptr);
The array is mutable, so we can change its contents (be careful not to write bytes beyond the end of
the array though). Fortunately, 'World' is no longer than 'Hello"
In this case, the char pointer ptr
strcpy(ary, "World"); // OK
strcpy(ptr, "World"); // NOT OK - Segmentation fault (crashes)
We can, however, unlike the array, we change ptrptr = "World"; // OK!
ptr = ary; // OK!
ary = (..anything..) ; // WONT COMPILE
// ary is doomed to always refer to the original array.
printf("%p : %s\n", ptr, ptr);
strcpy(ptr, "World"); // OK because now ptr is pointing to mutable memory (the array)
What to take away from this is that pointers * can point to any type of memory while C arrays [] can
only point to memory on the stack. In a more common case, pointers will point to heap memory in which
case the memory referred to by the pointer CAN be modified.sizeof()sizeof(ary)arysizeof(ptr)sizeof sizeof(char*) sizeof(char[])char str1[] = "will be 11";
char* str2 = "will be 8";
sizeof(str1) //11 because it is an array
sizeof(str2) //8 because it is a pointer
Be careful, using sizeof for the length of a string!int* f1(int *p) {
*p = 42;
return p;
} // This code is correct;
char* f2() {
char p[] = "Hello";
return p;
} // Incorrect!
Explanation: An array p is created on the stack for the correct size to hold H,e,l,l,o, and a null
byte i.e. (6) bytes. This array is stored on the stack and is invalid after we return from f2.char* f3() {
char *p = "Hello";
return p;
} // OK
Explanation: p is a pointer. It holds the address of the string constant. The string constant is
unchanged and valid even after f3 returns.char* f4() {
static char p[] = "Hello";
return p;
} // OK
Explanation: The array is static meaning it exists for the lifetime of the process (static variables
are not on the heap or the stack).int *space = malloc(sizeof(int) * 10);
void mystrcpy(char*dest, char* src) {
// void means no return value
while( *src ) { dest = src; src ++; dest++; }
}
In the above code it simply changes the dest pointer to point to source string. Also the nuls bytes
are not copied. Here's a better version -
while( *src ) { *dest = *src; src ++; dest++; }
*dest = *src;
Note it's also usual to see the following kind of implementation, which does everything inside the
expression test, including copying the nul byte.
while( (*dest++ = *src++ )) {};
// Use strlen+1 to find the zero byte...
char* mystrdup(char*source) {
char *p = (char *) malloc ( strlen(source)+1 );
strcpy(p,source);
return p;
}
int *n = (int *) malloc(sizeof(int));
*n = 10;
//Do some work
free(n);
int *p = malloc(sizeof(int));
free(p);
*p = 123; // Oops! - Dangling pointer! Writing to memory we don't own anymore
free(p); // Oops! - Double free!
The fix is first to write correct programs! Secondly, it's good programming hygiene to reset pointers
once the memory has been freed. This ensures the pointer can't be used incorrectly without the program
crashing.
Fix:
p = NULL; // Now you can't use this pointer by mistake
typedef float real;
real gravity = 10;
// Also typedef gives us an abstraction over the underlying type used.
// In the future, we only need to change this typedef if we
// wanted our physics library to use doubles instead of floats.
typedef struct link link_t;
//With structs, include the keyword 'struct' as part of the original types
In this class, we regularly typedef functions. A typedef for a function can be this for example
typedef int (*comparator)(void*,void*);
int greater_than(void* a, void* b){
return a > b;
}
comparator gt = greater_than;
This declares a function type comparator that accepts two
void*