A question about printf arguments. C/C++

拥有回忆 提交于 2020-01-13 11:27:07

问题


We have the following code fragment:

char tab[2][3] = {'1', '2', '\0', '3', '4', '\0'};
printf("%s\n", tab);

And I don't understand why we don't get an error / warning in the call to printf. I DO get a warning but not an error, and the program runs fine. It prints '12'.
printf is expecting an argument of type char *, i.e. a pointer to char. So if I declared char arr[3], then arr is an address of a memory unit which contains a char, so if I called printf with it, it would decay to pointer to char, i.e. char *.
Analogously, tab is an address of a memory unit that contains the type array of 3 char's which is in turn, an address of memory unit contains char, so tab will decay to char **, and it should be a problem, since printf is expecting a char *.

Can someone explain this issue?

Addendum:

The warning I get is:
a.c:6: warning: char format, different type arg (arg 2)


回答1:


Example Source

#include <stdio.h>

int main( void ) {
  char tab[2][3] = {'1', '2', '\0', '3', '4', '\0'};
  printf("%s\n", tab);

  return 0;
}

Compile Warning

$ gcc test.c
test.c: In function ‘main’:
test.c:5: warning: format ‘%s’ expects type ‘char *’, but argument 2 has type ‘char (*)[3]’

Pointers are Pointers

The %s argument to printf indicates to the function that it will be receiving a pointer (to a string). A string, in C, is merely a series of bytes terminated by an ASCII-Z. The tab[2][3] variable is a pointer. Some compilers will issue a warning about the pointer mismatch. However, the code should still print out 12 because printf's code traverses memory starting at the pointer it was given (printing characters as it goes) until it finds a zero byte. The 1, 2, and \0 are contiguously set in memory, starting at the address represented by the tab variable.

Experiment

As an experiment, what happens when you compile and run the following code:

#include <stdio.h>

int main( void ) {
  char tab[2][3] = {'1', '2', '\0', '3', '4', '\0'};
  printf("%s\n", tab[1]);

  return 0;
}

Don't be afraid of experimenting. See if you can come up with the answer based on what you now know. How would you reference tab now (in light of the experiment) to get rid of the warning and still display 12?




回答2:


The tab parameter matches the elipsis in the printf() call. C and C++ compilers are undfer no obligation to check such parameters.




回答3:


Your assumption that tab will decay to char ** is wrong: tab has type char [2][3], ie it will decay to char (*) [3]. It's important to understand that although arrays and pointers often behave alike, they are not the same thing. printf() expects a char *, so it takes the bits of the char (*) [3] and interprets them accordingly. Although it works on your platform, the C standard doesn't guarantee this: both pointers reference the same memory location, but their representation need not be identical.

Check my answer to this related question for details.




回答4:


You seem to have explained it yourself, I don't see what's left to say.

tab is an array of two char *'s. Each element of tab is a string that printf can accept, but tab itself is not acceptable, since it is a pointer to a pointer to a char.



来源:https://stackoverflow.com/questions/1057158/a-question-about-printf-arguments-c-c

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!