不同文件之间的变量用const修饰时

本文探讨了C++中全局变量的声明与定义差异,特别是extern关键字与const修饰符的使用,解释了为何缺少正确声明会导致链接错误。

一个文件:test1.cpp

#include"stdafx.h"
#include<conio.h>
#include<stdlib.h>


void func(void);

extern const int j;
extern const float i;
int main(void)
{
	
	printf("%d  %f\n",j,i);
	getche();
	return 0;
}

另一个写hao.cpp

#include"stdafx.h"
extern const int j=7;
extern const float i=1.3f;

发现hao.cpp如果j和i不加extern修饰的话显示    “无法解析的外部命令”错误,,,,而书上说定义全局变量时extern是可选的

而且在test1.cpp中extern声明中如果不加const也会显示同上的错误。

这个问题论坛上说:


Lactoferrin:很简单,因为int和const int不一样

lile1234_show:

在c++中const有限定变量作用域的作用,它限制变量只在本编译单元内可以使用.

heartszhang

没发完,不好意思。

从c++角度来说,楼主写法没问题,楼上的回答都不靠谱。

作为c++标准控,我用c++标准回答你。

首先,

extern const int j = 7;

是internal linkage还是external linkage?

答案是external。楼上很多人说const是internal,是的,const int j=7是internal但是extern const int j = 7是external。

C++标准规定,一个名字是internal linkage, 如果这个名字加了cosnt但是没有加extern。原文如下:

(A name having namespace scope (3.3.6) has internal linkage if it is the name of a variable that is explicitly declared const or constexpr and neither explicitly declared extern nor previously declared to have external linkage;)


所以extern const int j = 7是external linkage。


其次,为什么要在乎internal linkage还是external linkage呢?

因为c++标准规定:如果不同文件的2个名字都是external linkage,并且2个名字相同,那么他们是同一个名字。

所以楼主的const extern int j = 7和extern int j应该指代同一个东西。

标准原文如下,

Two names that are the same (Clause 3) and that are declared in different scopes shall denote the same variable, function, type, enumerator, template or namespace if 

— both names have external linkage or else both names have internal linkage and are declared in the same translation unit;


最后,关于楼主的链接错误。

test1.obj : error LNK2001: 无法解析的外部符号 "int j" (?j@@3HA)

这个链接错误说明linker无法找到j的定义。

我们再来看一下j是怎样定义的。

extern int j; //注意,这个不是j的定义,只是一个j的声明。

另一个文件,
extern const int j = 7; //这个才是j的定义。

关于声明和定义的区别就是声明只是告诉编译器这个名字存在,定义是告诉编译器真正的实体,如果要用这个名字的话,没有定义是不行的。例如,
int f(); //声明一个函数
int f() { return 0} //定义这个函数

为什么extern int j;不是定义呢?c++标准规定,如果加extern,同时又没有initialization的话,就是声明,否则就是定义。原文如下:

A declaration is a definition unless 
 - ...
 - ... it contains the extern specifier (7.1.1) or a linkage-specification25 (7.5) and neither an initializer nor a function body,

所以原因很清楚了,楼主的linker无法找到extern int j = 7;

或者是楼主编译器有问题,或者是楼主没有把extern int j = 7这个文件一起加进来编译。

cxsjabcabc

分析的不错,但是最后说的不对。声明在这个文件没有问题,外部也有定义,这就可行。
我在xcode的gcc4.2下面编译没有任何问题。
只能说这是编译器实现的不同,不是写的有问题。

hu7324829

链接时期错误, 比如说int j;在符号表里是_int_j_
const int j是_const_int_j_ 当然就找不到了

求解。。




当结构体变量用 `const` 修饰,意味着一旦初始化,其值就不能再被修改。因此,使用函数对其进行初始化,函数需要在初始化过程中提供所有必要的值。以下是几种常见的使用函数初始化 `const` 结构体变量的方法: ### 1. 返回结构体对象的函数 可以定义一个函数,该函数返回一个结构体对象,然后使用这个返回值来初始化 `const` 结构体变量。 ```cpp #include <iostream> #include <string> // 定义结构体 struct Person { std::string name; int age; }; // 函数返回一个 Person 结构体对象 Person createPerson(const std::string& name, int age) { return {name, age}; } int main() { // 使用函数返回值初始化 const 结构体变量 const Person person = createPerson("Alice", 25); // 输出结构体成员 std::cout << "Name: " << person.name << ", Age: " << person.age << std::endl; return 0; } ``` ### 2. 构造函数 如果结构体是一个类类型(即包含构造函数),可以使用构造函数来初始化 `const` 结构体变量。 ```cpp #include <iostream> #include <string> // 定义结构体(类类型) class Person { public: // 构造函数 Person(const std::string& name, int age) : name(name), age(age) {} std::string getName() const { return name; } int getAge() const { return age; } private: std::string name; int age; }; // 函数返回一个 Person 对象 Person createPerson(const std::string& name, int age) { return Person(name, age); } int main() { // 使用函数返回值初始化 const 结构体变量 const Person person = createPerson("Bob", 30); // 输出结构体成员 std::cout << "Name: " << person.getName() << ", Age: " << person.getAge() << std::endl; return 0; } ``` ### 3. 初始化结构体数组 如果要初始化 `const` 结构体数组,可以在函数中返回一个结构体数组或使用函数来填充数组元素。 ```cpp #include <iostream> #include <string> // 定义结构体 struct Person { std::string name; int age; }; // 函数返回一个 Person 结构体对象 Person createPerson(const std::string& name, int age) { return {name, age}; } int main() { // 使用函数初始化 const 结构体数组 const Person people[] = { createPerson("Alice", 25), createPerson("Bob", 30), createPerson("Charlie", 35) }; // 输出数组元素 for (size_t i = 0; i < sizeof(people) / sizeof(people[0]); ++i) { std::cout << "Name: " << people[i].name << ", Age: " << people[i].age << std::endl; } return 0; } ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值