Finding string size in argv using sizeof

This is more of a conceptual question at the moment than a practical one, but it really bothers me.

Say I have a c program called "test.c" and I want to find the number of spaces in the array for the word that the user enters as an argument. For example, "./test.c test_run" should print 9 because there are 8 characters, and then one for the zero termination character. When I try to use sizeof for argv, although I am having some problems.

int main(int argc, char *argv[]) { char buf10[10]; printf("The size of buf10 is: %i.\n", sizeof(buf10)); return 0; } 

Prints the result: "The size of buf10 is: 10. ". This makes sense because I selected a char array. In C, the size of a char is 1 byte. If I chose int, this number will be 4.

Now my question is: why can't I do this with argv?

 int main(int argc, char *argv[]) { printf("argv[1] has the value: %s\n", argv[1]); printf("strlen of argv[1] is: %i\n", strlen(argv[1])); printf("sizeof of argv[1] is: %i\n", sizeof(argv[1])); return 0; } 

Ran with "./test Hello_SO" gives the result:

 argv[1] has the value: Hello_SO strlen of argv[1] is: 8 sizeof of argv[1] is: 4 

The length of the line makes sense, since it should be 9, but minus "\ 0" is 8.

However, I do not understand why sizeof returns 4 (pointer size). I understand that * argv [] can be thought of as ** argv. But I have explained it already. In my first example, I type "buf", but here I type "argv [1]". I know that I could easily get the answer using strlen, but as I said earlier, this is just conceptual at the moment.

+5
source share
2 answers

Pointers and arrays are not the same thing, although in many situations they are very similar. sizeof is the key difference.

 int arr[10]; assert(sizeof arr == (sizeof(int) * 10)); int *ip; assert(sizeof ip == sizeof(int*)); 

The arr type is higher than int[10] . Another way to see the difference between array types and pointers is to use them.

 int i; ip = &i; // sure, fine arr = &i; // fails, can't assign to an int[10] 
Arrays

cannot be assigned.

What is confusing is that when you have an array as a function parameter, it is actually the same as the pointer.

 int f(int arr[10]) { int x; arr = &x; // fine, because arr is actually an int* assert(sizeof arr == sizeof(int*)); } 

To answer the question of why you cannot use sizeof argv[1] and get the size of the string (plus 1 for \0 ), this is because it is a dangling array. In this case, the first dimension has an unknown size, as well as the second. sizeof behaves like a compile-time operation in this case, and the length of the string is not known until runtime.

Consider the following program:

 #include <stdio.h> int main(int argc, char *argv[]) { printf("%zu\n", sizeof argv[1]); } 

Generated assembly:

 .LC0: .string "%zu\n" .text .globl main .type main, @function main: .LFB3: .cfi_startproc subq $8, %rsp .cfi_def_cfa_offset 16 movl $8, %esi # this 8 is the result of sizeof movl $.LC0, %edi # the format string movl $0, %eax call printf # calling printf movl $0, %eax addq $8, %rsp .cfi_def_cfa_offset 8 ret .cfi_endproc 

as you can see, the result of sizeof argv[1] is executed at compile time, nothing above calculates the length of the string. I'm on 64-bit, so my pointers are 8 bytes.

+3
source

The variable buf10 is known at compile time as an (contiguous) ten-character array. Other pointers are dynamically allocated and are pointers to character. This is why you get the size of the character array and sizeof (char *).

+1
source

Source: https://habr.com/ru/post/1203668/


All Articles