【问题标题】:Pointer to constant string in struct指向结构中常量字符串的指针
【发布时间】:2016-12-30 01:45:31
【问题描述】:

我正在用 C 语言编写。

header1.h 中,我声明了一个指向常量字符串(char 的常量数组)的指针,一个带有结构和该类型变量的新类型,以及另一个变量:

const char *str_ptr = "Hello world!";

struct entry_t {
const char *text;
int var;
};
typedef entry_t entry;

extern entry start_entry;

int a;

在文件func.c我定义了新变量:

#include "header1.h"

entry start_entry = {str_ptr, a};

void func(void)
{
    //here i use start_entry
}

但是编译器会报错

需要常量表达式

start_entry 的初始化,特别是const char* 成员的初始化。 为什么?哪里出错了?

当然,如果我将字符串定义为

const char str[] = "Hello world!";

然后entry 变量为

entry start_entry = {&str, a};

一切正常。

EDIT_1

我在报告我的代码时犯了两个错误:

  1. var 也是const

    结构入口_t { 常量字符*文本; 常量 int 变量; };

  2. 在func.c中entry也是const

    const entry start_entry;

EDIT_2

我不在乎 var,我的兴趣在于const char * 成员(即使问题可能是一样的:我之前写错了代码,也有int var 我有一个错误...)。 我要重新定义所有:

//header1.h

const char *str_ptr = "Hello world!";

struct entry_t {
const char *text;
};
typedef entry_t entry;

extern const entry start_entry;


//func.c
#include header1.h

const entry start_entry = {str_ptr};

void func(void)
{
    //here i use start_entry
}

我不明白为什么 start_entry 有一个 const char* 成员,我用 const char* 定义它,但有那个错误。

【问题讨论】:

  • 看起来您正在使用 C++ 编译器。在 C 中,显示的源代码中没有 entry_t 本身的定义。
  • 请提供一个最小、完整且可验证的示例:stackoverflow.com/help/mcve
  • 我敢打赌您使用的是非 gcc 编译器,对吧?您能告诉我们您使用的是哪个编译器吗?
  • entry start_entry = {&str, a}; 是错误,&str 是错误类型
  • 您的代码中还有另一个潜在的错误;如果两个不同的 .c 文件包含header.h,则astr_ptr 有多个定义。它们要么需要是static,要么只在标头中有extern 声明。

标签: c string pointers struct constants


【解决方案1】:

您只能在初始化程序中使用编译时常量。变量 str_ptr 甚至不是运行时常量。 const 限定符的作用是防止 str_ptr 指向的字符串被修改。指针本身可以重新分配。因此,您需要在初始化函数中初始化您的开始条目:

#include "header1.h"

entry start_entry;

void func(void)
{
    //here i use start_entry
}


void init(void)
{
    start_entry.text = str_ptr;
    start_entry.var = a;
}

【讨论】:

  • 或者最好只使用数组而不是无用的指针变量。
  • 这种初始化代码应该被高度反对,因为它很少是线程安全的并且会增加不必要的运行时成本,特别是如果你修复了线程安全问题。
  • 但是如果 start_entry 是 const,就像在 EDIT_1 中一样,我无法初始化它。
【解决方案2】:

问题在于,使用 C 编译器无法在全局范围内初始化此类语句,它被视为函数外的代码: (就像你不能调用函数来获取 tis 返回值并在函数外初始化全局)

entry start_entry = {str_ptr, a};

str_ptr 在 C 中并不真正被视为常量,因为它被视为指针。 const 限定符在这里什么都不做。

a BTW 我也遇到了这个问题,看起来你使用了一些奇怪的 C++ 编译器或特殊的 C99 选项,请参阅 pmg 评论)

当简单地调用g++ 时,您的示例有效。

注意您的“自然”陈述

entry start_entry = {&str, a};

编译(使用你的编译器,gcc 仍然会因为 a 而拒绝它)但是因为你传递了指针的 地址,而不是指针本身 => 未指定的行为:不好。

如果你想这样做,我建议你使用 C++ 编译器。

简单的 gcc 调用有什么作用:

char str_ptr[] = "Hello world!";
entry start_entry = {str_ptr, 12}; // considered as an array, value decided by the compiler, even if const keyword is missing

什么没有

const char *str_ptr = "Hello world!";
entry start_entry = {str_ptr, 12}; // str_ptr is considered as a variable pointer even if const

entry start_entry = {"Hello world!", a}; // a is a variable: nocantdo

你是对的,char [] 告诉编译器指针是常量,即使没有 const 关键字顺便说一句,而 const 关键字不被考虑在内。

注意事项:

我必须修复您的代码,以便使用我的 gcc 编译器进行编译:

typedef struct  {
const char *text;
int var;
} entry;

extern entry start_entry;

另一点是:避免在头文件中声明全局变量,因为如果你有多个代码文件包含它,你会得到多个包含或未定义的符号。

【讨论】:

  • "char [] 告诉编译器指针是常量" - 不,不涉及指针
  • "entry start_entry = {&str, a}; 工作但不是您所期望的,因为您传递的是指针的地址,而不是指针本身!" " - str 没有定义为指针,所以我不应该将它的地址传递给 start_entry 的指针吗?
  • @BzFr entry start_entry = {&str, a}; 不起作用,这是违反约束
  • @M.M:为什么?如何正确初始化变量start_entry
  • 我的意思是 entry start_entry = {&str, a}; 编译,你的编译器很好(因为 gcc 不会接受 a,因为它不是常量),但在执行时会崩溃。
猜你喜欢
  • 2020-03-25
  • 2020-03-23
  • 2015-06-22
  • 1970-01-01
  • 1970-01-01
  • 2013-08-02
  • 2020-10-30
  • 1970-01-01
  • 2012-02-07
相关资源
最近更新 更多