【问题标题】:Why does the printf fail to print Jack and George's names? [duplicate]为什么 printf 不能打印 Jack 和 George 的名字? [复制]
【发布时间】:2019-05-06 09:16:41
【问题描述】:

我想知道为什么杰克和乔治的名字没有打印出来。我尝试在结构中添加另一个成员,名称会正常打印,这是为什么呢?如果有人可以提供帮助,我将不胜感激。代码如下:

    #include <stdio.h>
    typedef unsigned short int u16;
    typedef unsigned char u8;
    typedef struct 
    {
     u8 name[10];
     u16 salary;
     u16 bonus;
     u16 deduction;
     //u8 x;//why does the printed name get ruined 
     //without this?
     }employee;
     void main (void)
     {
       employee arr[3]={{.name = "John"},{.name = 
        "Jack"},{.name = "George"}};
       u16 i = 0;
       u16 sum = 0; 
       for (i = 0; i < 3; i++)
{
    printf("\nPlease enter %s's Salary:",arr[i].name);
    scanf(" %d",&arr[i].salary);
    printf("\nPlease enter %s's Bonus:",arr[i].name);
    scanf(" %d",&arr[i].bonus);
    printf("\nPlease enter %s's Deduction:",arr[i].name);
    scanf(" %d",&arr[i].deduction);
    sum = sum + arr[i].salary + arr[i].bonus - arr[i].deduction;
}
    printf("\nTotal value needed is: %d",sum);
}

【问题讨论】:

  • 您在scanf 中使用了错误的格式说明符,这会导致内存损坏。一个简单的解决方法是改为阅读 int 而不是“u16”(无论如何您都不应该定义自己,因为该语言已经提供了固定宽度类型)
  • 开启所有警告(见MM评论)
  • %hu 在这种情况下是正确的。但我建议阅读int,然后将其分配回您的结构字段。
  • 如果是内存损坏,那么更改内存的“形状”(例如通过在堆栈上添加更多字段或变量)有时会导致损坏发生在部分未使用的内存,或用于其他用途的内存(导致没有症状或不同的症状)

标签: c arrays struct printf


【解决方案1】:

这是因为您的 scanf() 错误,并且正在覆盖您的结构的成员。

一个体面的编译器会发出很多非常严重的警告:

$ gcc -Wall t.c
t.c:13:11: warning: return type of ‘main’ is not ‘int’ [-Wmain]
      void main (void)
           ^~~~
t.c: In function ‘main’:
t.c:22:14: warning: format ‘%d’ expects argument of type ‘int *’, but argument 2 has type ‘u16 *’ {aka ‘short unsigned int *’} [-Wformat=]
     scanf(" %d",&arr[i].salary);
             ~^  ~~~~~~~~~~~~~~
             %hd
t.c:24:14: warning: format ‘%d’ expects argument of type ‘int *’, but argument 2 has type ‘u16 *’ {aka ‘short unsigned int *’} [-Wformat=]
     scanf(" %d",&arr[i].bonus);
             ~^  ~~~~~~~~~~~~~
             %hd
t.c:26:14: warning: format ‘%d’ expects argument of type ‘int *’, but argument 2 has type ‘u16 *’ {aka ‘short unsigned int *’} [-Wformat=]
     scanf(" %d",&arr[i].deduction);
             ~^  ~~~~~~~~~~~~~~~~~
             %hd

当您调用 scanf(" %d",&amp;arr[i].salary); 时,%d 表示将您读取的数字存储为 int 类型。

但是,您已将salary 声明为u16 类型,在您的系统上它可能比int 小很多。 scanf jsut 假设您在提供 %d 时说的是真话,并在 &amp;arr[i].salary 指针指向的任何地方存储一个 int,覆盖该变量之后的内存,这可能会覆盖和丢弃 name 数组。

所以要么

  • 将您的salary, bonus and deduction 声明为int 而不是u16,因此它与您提供给scanf%d 参数相匹配 或
  • scanf 为您的u16 变量提供适当的类型说明符,即%hu

例如

   scanf(" %hu",&arr[i].salary);
   scanf(" %hu",&arr[i].bonus);
   scanf(" %hu",&arr[i].deduction);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-04-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-21
    • 1970-01-01
    • 2020-01-10
    • 2013-01-05
    相关资源
    最近更新 更多