【问题标题】:formatter size in printf()printf() 中的格式化程序大小
【发布时间】:2013-08-19 03:02:26
【问题描述】:

关于问题Why do I have to specify data type each time in C?和我之前的问题how to read memory bytes one by one in hex(so without any format) with printf()

是否可以为我澄清以下问题?

int32_t a[3]={21,3,1000031}; 
char* p1=&a[0]; /* char is 1-bye and &a[0] is 0x0004 for example */

printf("p1 in hex=%x\n",*p1); /* 4 bytes starting from word-aligned address p1 */
printf("(p1+3)=%d",(p1+3));   /* 4 bytes starting from a NON word-aligned address?* line 2 printf */
printf("p1+3=%p",p1+3) /* line 3 print*/

%x 和 %d 总是 告诉 printf 使用 int 格式,在我的电脑中是 4 字节?我说的对吗?

(p1+3) 是一个非字对齐的地址 Ox004+3=0x007,那么在这种情况下 printf() 显示了什么?换句话说,第 2 行涉及哪些字节打印?

另外,%p formatter(void *) 是否需要 1 个字节来读取(因为 char)或者因为我们谈论指针并且它们总是占用 4 个字节(一个字)?

总结一下我的问题,%d %x %p,.. 他们是从内存中读取恒定大小(取决于 pc)还是取决于相应参数的大小?

【问题讨论】:

  • printf("%d", sizeof(int)); 会告诉您int 在您的系统中有多少字节。
  • 您应该使用%zu 打印size_t,而不是%d
  • @CarlNorum:很高兴知道:)

标签: c printf


【解决方案1】:

可变参数,就像在 C 中传递的所有其他参数一样,只是按值传递。你的案子没有任何地址。不过,在某些情况下,您正在打印指针变量的 value。我将尝试按顺序解释:

  1. 第一:

    printf("p1 in hex=%x\n",*p1);
    

    *p1 的任何内容打印为十六进制数字。那是150,具体取决于您分别使用的是little-endian 机器还是big-endian 机器。

  2. 下一步:

    printf("(p1+3)=%d",(p1+3));
    

    将尝试将p1 + 3 的任何内容打印为十进制数。由于p1 是一个指针,所以这并不是一件明智的事情,从技术上讲,这个语句会导致未定义的行为。您应该使用%p 来打印指针。假设指针和int 在您的机器上大小相同,您可能会得到一些数字,但可能不是一个真正有意义的数字。

  3. 最后:

    printf("p1+3=%p",p1+3)
    

    %p 打印一个指针类型,所以这一行是正确的。您将(可能)获得与 #2 中相同的值,但十六进制格式除外。不过,这都是特定于机器/实现的。

关于您的其他问题:

%x%d 总是告诉 printf 使用 int 格式,在我的电脑中是 4 字节?我说的对吗?

%x 用于unsigned int%d 用于int%x 会给你十六进制输出,%d 十进制输出。如果 int 在您的机器上是一个四字节类型,它们都会打印您传递的相应 4 字节的参数。

(p1+3) 是一个非字对齐地址 Ox004+3=0x007,那么在这种情况下 printf() 显示了什么?换句话说,第 2 行 printf 涉及哪些字节?

由于您正在打印指针值本身,因此对齐是没有意义的。不过,您不应该使用%d 来执行此操作(如上所述)。有问题的地址可能不是7,或者......我不太确定你从哪里得到的。

另外,%p formatter(void *) 是否需要 1 个字节来读取(因为 char)或者因为我们谈论指针并且它们总是占用 4 个字节(一个字)?

%p 必须与 void * 参数配对,如您所说。它将为您的机器上的指针类型打印适当的大小(在您的情况下听起来像 4 个字节)。

总结一下我的问题,%d%x%p,.. 他们是从内存中读取一个恒定大小(取决于 pc)还是取决于它们相应参数的大小?

他们不一定从内存中读取任何内容 - 这取决于您的 ABI 的工作方式以及您机器的可变参数函数的调用约定。您必须匹配格式说明符和相应变量之间的类型,否则会导致未定义的行为。

【讨论】:

  • 你能告诉我这个的输出是什么吗:: printf("(p1+3)=%d",*(p1+3)); //非字对齐
  • 你对打印的内容有什么想法吗: printf("(p1+3)=%d",*(p1+3)); //非字对齐
  • 这取决于您的机器是小端还是大端以及char 的位。我猜是021
【解决方案2】:

我认为您的代码没有清楚地显示您想问什么,而是回答您的总结问题:

%d %x %p,.. 他们是从内存中读取一个恒定大小(取决于 pc)还是取决于他们相应参数的大小?

他们读取的大小取决于机器上特定类型的大小。例如,对于 32 位机器,%d 将读取 4 个字节,因为它假定变量是 int

我认为这段代码说明了大致的思路:

int a = 1089;
printf("%c\n", a);  // prints "A" on a little-endian machine
printf("%d\n", a);  // prints "1089"

【讨论】:

  • 我的代码没有显示任何内容。我只是在玩指针和 printf()。在上面的代码中,我认为 printf() 的第二个参数只是给出了这个函数,即变量的第一个字节地址。那么 printf() 的第一个参数显示从该地址开始从内存中读取多少字节。
  • 在大端机器(SPARC、PPC)上,您的 %c 示例将打印空字节,而不是 A。在 little-endian 机器上,它可以正常工作。
  • @YuHao 你能告诉我这个的输出是什么吗:: printf("(p1+3)=%d",*(p1+3)); //nonword-align也在First 1-中,当你说代码将*p打印为十六进制时,在我看来printf不知道有多少字节构成*p,它会查看它的第一个参数是 %x,所以需要 4 个字节。(它不看 int32_t 来决定 4 个字节)。
猜你喜欢
  • 2019-10-18
  • 2019-07-01
  • 2010-10-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-11
  • 1970-01-01
相关资源
最近更新 更多