【问题标题】:assigning variable outside main: data definition has no type or storage class [duplicate]在main之外分配变量:数据定义没有类型或存储类[重复]
【发布时间】:2020-10-13 23:55:10
【问题描述】:

为什么是这个代码:

#include <stdio.h>
#include <stdlib.h>

int *mem;
*mem = 3;
int main(){
    int *mem2 = malloc(4*4);
    mem=mem2;
    for(int i =0; i<4 ; i++)
        mem[i]=i;

    printf("%i\n",mem[2]);
}

正在发出警告:

a.c:5:1: warning: data definition has no type or storage class
 *mem = 3;
 ^
a.c:5:2: warning: type defaults to ‘int’ in declaration of ‘mem’ [-Wimplicit-int]
 *mem = 3;
  ^~~
a.c:5:8: warning: initialization of ‘int *’ from ‘int’ makes pointer from integer without a cast [-Wint-conversion]
 *mem = 3;
  1. mem 没有类型或存储,但它应该是 (int*) 类型

  2. type 默认为 int,但 mem 已经有 type

为什么问题出在 main 之外?我没有函数或逻辑,只有 simple 赋值,那为什么会出现问题?组装完成后,mem 驻留在文本段中,而不是数据段(奇怪),否则它通常通过 rip-relative 模式访问(例如 mov %rax, mem(%rip)),所以这里没有问题。

    .text
    .globl  mem
    .data
    .align 8
    .type   mem, @object
    .size   mem, 8
mem:
    .quad   3
    .section    .rodata
.LC0:
    .string "%i\n"
    .text
    .globl  main
    .type   main, @function
main:
    ...

【问题讨论】:

  • 您不能将*mem = 3; 排除在函数之外。请注意,即使您在没有将 mem 初始化为有效地址的函数中也有此功能,您也无法执行 *mem = 3; 否则行为未定义。还做malloc(4*4); 你假设int 的大小是4,最好做malloc(4*sizeof(int));malloc(4*sizeof(*mem2)); 让编译器以安全的方式完成这项工作
  • 这不是汇编语言的问题,问题是 C 语言的设计以及函数之外的代码是如何解析的/编译器如何试图理解它。我修复了问题上的标签以反映错误消息的真正原因。另外,不,mem 不会出现在文本段中,这不合理,因为它不是 const
  • @PeterCordes 您可以查看编辑。在.text 或.rodata 中(mem 在.text 范围内,但在内部定义为.section .rodata),但不一定在数据段中
  • 如果它不在 main 中,并且没有被 main 调用,您希望该分配何时运行?
  • @stark 正如上面的评论,我不太确定。定义“下”.text 段,但在标签定义中,有.section .rodate。我不知道一个段/节的范围有多长,所以我不知道它属于什么

标签: c memory malloc language-design


【解决方案1】:

在任何函数之外,您只能使用声明。所以编译器试图解释这个语句

*mem = 3;

作为没有类型说明符的声明。

a.c:5:1: warning: data definition has no type or storage class
 *mem = 3;
 ^

为了支持与旧 C 标准的向后兼容性,编译器默认使用类型说明符 int

注意,如果你将这段代码放在sn-p

int *mem;
*mem = 3;

但在函数内部,它将具有未定义的行为,因为指针 mem 未指向 int 类型的有效对象。

【讨论】:

    【解决方案2】:

    以下内容是非法的。即使不是,这也是未定义的行为。

    int *mem;
    *mem = 3;
    int main(){
    }
    

    如果必须,您可以将其更改为以下内容:

    int num = 3;
    int *mem = &num;
    int main(){
    }
    

    正如@bruno 所指出的,以下可能会按预期工作,但不可移植:

    int *mem2 = malloc(4*4);
    

    为了便于携带,请将其更改为以下之一:

    int *mem2 = malloc(4 * sizeof(int));
    int *mem2 = malloc(4 * sizeof(*mem2));
    

    第二个选项被认为更好,因为如果将mem2 的类型更改为double,它不会导致运行时错误。

    【讨论】:

    • 我鼓励你也谈谈malloc(4*4); 以消除关于int 大小的假设
    • @bruno 甚至没有阅读那部分代码。好建议。
    猜你喜欢
    • 2012-03-13
    • 2014-08-18
    • 1970-01-01
    • 2022-12-04
    • 1970-01-01
    • 2018-10-22
    • 2013-09-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多