Part 1: Introduction
1.%p for pointer, %s for string, %d for integer, &ptr is the own address, *ptr is the pointed thing, ptr is pointed address
int* ptr = (int*)malloc(sizeof(int));
*ptr = 10;
printf("%d\n",*ptr);
printf("%p\n",ptr);
printf("%p\n",&ptr);
2. difference between array string and pointer string
char arr[] = "Wo Ai Sun Yi Hang";
char *ptr = "Wo Ai Sun Yi Hang";
strcpy(arr,"SYH");
strcpy(ptr,"SYH");//FAIL pointer is pointing to a read only memory
Array can only point to stack. ptr can point to any memory. It can't be changed when pointing to a read only memory.
3.size of *ptr and arr[]
char arr[] = "SYHAW";
char* ptr = "WASYH";
sizeof(arr);//6;
sizeof(ptr);//8 because ptr is a pointer
int* f1(int *p) {//OK,pointer point to another integer
*p = 42;
return p;
}
char* f2() {//FAIL, array is pointing to stack, invalid afer return
char p[] = "Hello";
return p;
}
char* f3() {//OK, string contans don't change
char *p = "Hello";
return p;
}
char* f4() {//OK, static will keep it after return, static not on stack or heap
static char p[] = "Hello";
return p;
}
4.difference between strcpy() and strdup()
strdup() will malloc enough space and then call strcpy(). It is more safe than strcpy and won't overflow, but need to be free.
Part 2. Text Input and Output
1.Different kind of print:
printf("%d and %s\n", int, str);
putchar(char);
puts(ptr*);
fprintf(file,"%d and %s\n", int, str);
dprintf(fd,"%d and %s\n", int, str);
perror(const char* message) will print to stderr
2.gets() is dangerous
gets() assume that the space is enough and has been removed. Now we are using fgets and getline()
- char* fgets(char *str, int num, FILE *stream); will trancate there is no more space. It will copy "\n" as will, need to be changed into "\0"
- ssize_t getline(char **lineptr, size_t *n, FILE *stream) is better because it will automaticlly alloc enough space. But it need to be freed.
char buff[10];
fgets(buff, sizeof(buff), stdin);
if(buff[strlen(buff)-1] == '\n'){
buff[strlen(buff)-1] = '\0';
}
char* buffer = NULL;
size_t size = 0;
ssize_t char = getline(&buffer, *size, stdin);
if(char>0 && buffer[strlen(buffer)-1]=='\n'){
buffer[strlen(buffer)-1] = '\0';
}
char = getline(&buffer, *size, stdin); //read another line
free(buffer);
}
Part 3: Common Gotchas
-
- String is read only and immutable.
-
- Underflow/Overflow
-
- Out of Scope
-
- sizeof(type *) and sizeof(type)
-
- String require strlen(s)+1 bytes
-
- Malloc won't initialize memory
-
- Double free/ use after free
-
- Need to copy getline buffer, it reuse the same buffer
-
- Forgot break
-
- if((x = 42)) instead of if(x = 42)
-
- Global variable and static variable will be initialized as 0
Part 4: String
char* strcpy(char*dest, char*src);
char* strncpy(char*dest, char*src, size_t n);
char* strcat(char*dest, char* src);
char* strncat(char* dest, char* src, size_t n);
int strcmp(char* dest, char* src); //compare, will return 0 if they are equal
int strncmp(char* dest, char* src, size_t n);
void* memcopy(void* dest, void* src, size_t n);
void* memset(void* b, int c, size_t len); // set first n to be c
Review Questions:
Q 1.1: Global variable and static variable will be initialized as 0 Q 1.2: Calloc will initialize to 0 Q 1.3: Need strlen()+1 Q 1.4a: Malloc didn't initialize Q 1.4b: First, sizeof(src) is always 8. Second, array point to stack, will be free after return Q 1.5: First is valid, string is imutable Q 1.6: Q 1.7: Q 1.8:
char* strcat(char* dest,const char* src){
int len = sizeof(*dest) - 1;
char* end = NULL;
for(; len >= 0; len--){
if(len == 0 && dest[0] == NULL){
end = dest[0];
}
if((dest[len]==NULL)&&(dest[len-1]!=NULL)){
end = dest[len];
break;
}
}
strcpy(end, src);
return dest;
}
Q 1.9: find the first null char Q 1.10: const variable can't be changed Q 2.1: no file stream Q 3.1: "w+", fprintf(f, "%s score is %d", name, score);
Exam Practice
1. What are the differences between a library call and a system call? Include an example of each.
System call is inside kernel and very costly. man 2 is System, man 3 is Library.
2. What is the *operator in C? What is the & operator? Give an example of each.
char* str = "Wo ai ni";
printf("%p",ptr);
printf("%s",*ptr);
printf("%p",&ptr);
3.When is strlen(s) != 1+strlen(s+1) ? When the length of s is 1. (sizeof() will count \0 at the end of string)
If s is '\0'.
4.How are C strings represented in memory? What is the wrong with malloc(strlen(s)) when copying strings?
A bunch of bytes until reach the '\0' pr NULL. Need strlen(s)+1 space.
5.mplement a truncation function void trunc(char*s,size_t max) to ensure strings are not too long with the following edge cases.
void trunc(char*s, size_t max){
if(strlen(s) < max || s == NULL){
return;
}
for(int i=max; i<strlen(s); i++){
s[i] = '\0';
}
return;
}
6.Complete the following function to create a deep-copy on the heap of the argv array. Set the result pointer to point to your array. The only library calls you may use are malloc and memcpy. You may not use strdup.
void duplicate(char** argc, char** result){
int size = sizeof(argc)/sizeof(argc[0]);
char** result = malloc(sizeof(argc));
for(int i = 0; i < size; i++){
memcpy(result[i],argc[i],sizeof(*result[i]));
}
return;
}