【问题标题】:Are characters passed as integers to called functions?字符是否作为整数传递给被调用函数?
【发布时间】:2015-02-18 23:12:49
【问题描述】:

我在下面写了一个 C 程序来调用具有可变数量参数的函数。

#include<stdio.h>
#include<stdarg.h>

void display(int, int, ...);

int main()
{
    display(1,5,1,2,3,4,5);
    display(2,3,'A','B','C');
    printf("\n");
    return 0;
}

void display(int type, int tot_num, ...)
{
    int i, j;
    char c;

    va_list ptr;
    va_start (ptr, tot_num);

    switch(type)
    {
            case 1:
            for (j=0; j<tot_num; j++)
            {
                    i = va_arg (ptr, int);
                    printf("%d ",i);

            }
            break;

            case 2:
            for (j=0; j<tot_num; j++)
            {
                    c = va_arg(ptr, char);
                    printf("%c ",c);
            }
    }
}

但是,当我编译程序时,我收到了来自 gcc 的以下警告。

-bash-4.1$ gcc varArg3.c
varArg3.c: In function âdisplayâ:
varArg3.c:41: warning: âcharâ is promoted to âintâ when passed through â...â
varArg3.c:41: note: (so you should pass âintâ not âcharâ to âva_argâ)
varArg3.c:41: note: if this code is reached, the program will abort
-bash-4.1$

第 41 行是c = va_arg(ptr, char);

当我阅读 va_arg 的 man 3 页面时,它被提到如下:

如果没有 next 参数,或者 type 与实际 next 参数的类型不兼容(根据默认参数提升),则会发生随机错误。

当我读到这篇文章时,我认为c = va_arg(ptr, char); 是正确的,因为变量参数列表中的数据是 characters 。但是 gcc 的上述警告表明传递的变量参数不是真正的字符而是整数。

按照 gcc 的建议,我将其更改为 c = va_arg(ptr, int);,现在我没有收到任何警告。当我运行程序时,我也会得到预期的输出。

那么,字符(在main() 中对diplay() 的第二次调用)是否作为整数传递给display()

谢谢。

【问题讨论】:

  • 据我记得,char literals(您正在传递的)实际上在 C 中存储为 int 类型。如果这是错误的,我相信有人会纠正我。
  • 是的,'A'int。另外,stackoverflow.com/questions/1255775/…
  • @LeeDanielCrocker 感谢您的链接。会经历的。

标签: c gcc integer character variadic-functions


【解决方案1】:

'A' 的类型是 int,试试这个

printf("typeof('A') == typeof(int) -> %s\n", 
         (sizeof('A') == sizeof(int)) ? "YES" : "NO");

自己检查一下。

编辑
根据Jonathan Leffler的评论,即使你这样做了也会发出警告

char a = 'A';

然后通过a,因为无论如何都会提升为int,所以也就意味着

int arg = va_arg(ptr, int);

总是正确的,评论中提到的标准部分说明如下

§6.5.2.2

7。如果表示被调用函数的表达式具有包含原型的类型, 参数被隐式转换,就像通过赋值一样,转换为 对应的参数,取每个参数的类型为不合格版本 其声明的类型。函数原型声明器中的省略号表示 参数类型转换在最后一个声明的参数之后停止。默认参数 提升是在尾随参数上执行的。

【讨论】:

  • 但即使额外的参数是char a = 'A';display(2, 3, a, a, a),值也会作为int 传递,而不是char,因为默认参数提升 (6.5.2.2 函数调用,C11 标准中的第 7 段)。
  • @iharob 是的,检查过。但在那之后我有一个问题,“如果我将一个 char 传递给一个函数并将其存储在被调用函数的 char 变量中,这怎么可能?int 需要 4 个字节?char 有 1 个字节?” 但我又想,“等一下,字符是 1 个字节,所以它们只能取 2 (pow)8 - 1 的值,所以如果我传递一个值的整数,我等于或小于 2(pow )8 - 1,那么我当然可以将它存储在 char 变量中。"我的理解对吗?
  • @1Byn 是的,没错。如果你传递一个更大的值,你会遇到问题。但是只要值只需要1个字节就没有问题了。
猜你喜欢
  • 2021-07-24
  • 2019-06-24
  • 2013-02-21
  • 1970-01-01
  • 1970-01-01
  • 2016-02-23
  • 1970-01-01
  • 2018-03-01
  • 1970-01-01
相关资源
最近更新 更多