在下面的代码中,为什么多个声明(和一个定义)适用于全局变量x,而不适用y于main()函数内部的局部变量?它显示以下2个错误:
1)没有联系的'y'重新声明
2)之前的'y'声明就在这里
为什么它显示局部变量但不是全局变量的错误?不仅是我的书,而且本论坛的以下2个链接清楚地表明我们可以多次声明一个变量(尽管只定义一次).
并且请注意解释第一个错误"没有链接"的部分是什么,"没有连接的'y'的重新声明"是什么意思?什么联系和谁?将局部变量链接到哪里?
#include<stdio.h>
int x;
int x;
int x=303;
int main(void)
{
int y;
int y;
int y=776; //Works fine if above 2 declarations are removed!!
printf("The value of x is %d,and of y is %d",x,y);
}
Run Code Online (Sandbox Code Playgroud) "R.."这个论坛上一位备受赞誉的撰稿人在2天后明确告诉我:
Initializers for objects of static storage duration must be constant expressions. The result of a function call is not a constant expression.
他在讨论全局变量.但是我不确定main()函数内部声明的常量是什么,或者任何函数.尽管直觉上我觉得即使对于在函数内声明的常量也是如此,以下程序来自以下链接凭借其所谓的correct答案,令我感到困惑.
http://www.indiabix.com/c-programming/const/discussion-546
#include<stdio.h>
int get();
int main()
{
const int x = get();
printf("%d", x);
return 0;
}
int get()
{
return 20;
}
Run Code Online (Sandbox Code Playgroud)
那么有人可以解释在C中是否有效为常量赋值?
一个80k信誉贡献者R.,跟我上,使我们无法与函数的返回值初始化全局变量,这不是被认为是恒定的,和全局变量必须用他的话一constant.And真正的初始化,我得到正如预期的那样,该程序出现以下错误 - .这initializer element is not a constant是程序:
#include<stdio.h>
int foo();
int gvar=foo(); //ERROR
int main()
{
printf("%d",gvar);
}
int foo()
{
return 8;
}
Run Code Online (Sandbox Code Playgroud)
但在这种情况下,我只是不明白为什么上面程序的后续更改版本根本没有显示任何错误并且工作正常.在第二个程序中,我使用相同函数的返回值初始化相同的全局变量foo().你能告诉我这种结果变化的严格技术原因是什么?为什么用函数的返回值初始化全局变量会导致错误,但同样的返回值初始化工作正常功能?
#include<stdio.h>
int foo();
int gvar;
int main()
{
gvar=foo();
printf("%d",gvar);
}
int foo()
{
return 8;
}
Run Code Online (Sandbox Code Playgroud)
产量 8
在下面的程序中,strtok()主要部分按预期工作,但我无法理解一个发现背后的原因.我读过strtok()这个:
为了确定令牌的开始和结束,该函数首先从起始位置扫描未包含在分隔符中的第一个字符(它成为令牌的开头).然后从令牌的开头开始扫描包含在分隔符中的第一个字符,这将成为令牌的结尾.
而且正如我们所知,在每个令牌的末尾strtok()放置一个\0.但是在下面的程序中,最后一个分隔符是一个点(.),之后在该点和引号()之间有Toad".现在点是我程序中的分隔符,但是在Toad之后没有分隔符,甚至没有空格(在我的程序中是分隔符).请清除以下因此产生的混淆:
为什么strtok()将Toad视为令牌,即使它不在2个分隔符之间?这是我strtok()遇到NULL字符(\0)时读到的内容:
一旦在strtok的调用中找到了str的终止空字符,所有后续调用此函数并使用空指针作为第一个参数返回空指针.
没有任何地方说过,一旦遇到空字符,就会返回一个指向令牌开头的指针(我们甚至没有令牌,因为我们没有得到令牌的结尾,因为没有找到分隔符字符在从令牌的开头开始扫描之后(即从Toad的'T'开始),我们只发现了一个空字符,而不是一个分隔符.那么为什么参数字符串的最后一个分隔符和引号之间的部分被认为是一个标记strtok()?请解释一下.
#include <stdio.h>
#include <string.h>
int main ()
{
char str[] =" Falcon,eagle-hawk..;buzzard,gull..pigeon sparrow,hen;owl.Toad";
char * pch=strtok(str," ;,.-");
while (pch != NULL)
{
printf ("%s\n",pch);
pch = strtok (NULL, " ;,.-");
}
return 0; …Run Code Online (Sandbox Code Playgroud) 在下面的程序中,我使用了两个函数prd()和display().我在main()中调用之前没有声明它们都在main()之前,并且我在main()之后定义了两个函数.然而,prd( )在main()内部顺利工作,调用display()显示警告"'display'的上一个隐式声明在这里".有什么不同display()有警告,但没有其他功能prd() ?我已经宣布它们都没有开始.由于调用了一个警告,但是其他一个工作正常.
#include<stdio.h>
int main()
{
int x=8,y=11;
printf("The product of %d & %d is %d",x,y,prd(x,y));
display();
return 0;
}
int prd(int x,int y)
{
return x*y;
}
void display()
{
printf("\n Good Morning");
}
Run Code Online (Sandbox Code Playgroud)
PS:如果你能回答这个次要问题,我真的很感激 - "C中是否根本没有必要的函数声明,只要它有定义吗?".我习惯在主要之前声明程序的所有功能()函数,然后在main()函数之后定义它们.我错了吗?
我对整个序列点的理解是基本的.我所拥有的只是一些粗略直观的想法,"一旦遇到序列点,我们就可以确定先前评估的所有副作用都已完成".我还读到,在语句中printf("%d",a++,++a,a++),行为未定义,因为逗号不表示序列点,而分号则表示.因此,我觉得一个非常严谨和确凿的答案对我有很大帮助,而不是通过直觉猜测和思考.
C语言中的以下类型的语句也是安全可靠的:
int a=4,*ptr=&a; //Statement 1
x+=4,y=x*2; //Statement 2 (Assume x and y are integer variables)
Run Code Online (Sandbox Code Playgroud)
如果有,怎么样?特别是在第二种情况下,如果逗号不是一个序列点,那么在我们在赋值中使用它之前,我们怎么能确定它x是否增加了?对于第一个语句,在分配地址之前,如何确定已初始化并分配内存?我是否应该安全地使用以下内容:4y=x*2aptr
int a=4,*ptr;
ptr=&a;
Run Code Online (Sandbox Code Playgroud)
和
x+=4;
y=x*2;
Run Code Online (Sandbox Code Playgroud)
编辑我对逗号运算符的理解告诉我这些语句是安全的.但是在阅读了关于序列点以及类似事物printf("%d",a++,++a,a++)未定义之后,我有了第二个想法.
位字段的字段部分似乎表明它们只能是结构或联合内的字段。
位字段可以是典型的“独立”变量,位于任何聚合数据类型(例如联合或结构)之外,如下所示:
int sum:6; //Can this work as a declaration statement?
sum=4;
Run Code Online (Sandbox Code Playgroud)
如果不是,为什么会这样?如果位域基本上是为了使用更少的内存,那么如果我们知道任何变量不会超过该大小,为什么不能将其声明为位域呢?
什么样的库函数会对errno产生什么样的错误并将其设置为非零值?在我的下面的程序中,我打算用if(errno!=0)一个条件来检查我使用的库函数是否正常运行,这就是我找到的(参见下面的代码):
首先我用来if(errno!=0)测试文件是否已成功打开fopen().如果我尝试打开一个不存在的文件,则errno设置为非零(在我的情况下为2),并通过打印errno每个阶段的值来验证它.但是,如果我打开现有文件,则errno的值保持为零,因为fopen()正确打开文件.在这件事上,if(errno!=0)作为if(pFile==NULL)我所评论的完美替代品.
如果文件成功打开,errno静止0,则控件移动到第一个else块.这是我发现关于行为的混淆的地方errno.在这里,由于我已经在r(读)模式下打开文件并尝试使用它来写入fputc(),我希望得到的写错误设置errno为非零,就像fopen()它无法成功打开文件时设置的那样.但errno即使在写入失败后,该值仍然为零fputc().(这可以通过errno错误写入后的打印值来验证).
为什么会这样?为什么一个函数fopen()设置了I/O错误设置errno其他函数所面临的while写错误fputc()不影响errno?如果是这样,我们怎样才能可靠地errno用作错误指标?我是否使用errno来测试fopen()是否成功运行,而不是"if(pFile == NULL)"不明智?我将非常感谢您对此的分析答案.
#include <stdio.h>
#include <errno.h>
int main ()
{
FILE * pFile;
printf("%d\n",errno);
pFile = fopen("D:\\decrypt.txt","r");
printf("%d\n",errno); // Prints 0 if …Run Code Online (Sandbox Code Playgroud) 我有两个.c文件:A1.c和A2.c
A1.c如下:
int i=0;
void main()
{}
Run Code Online (Sandbox Code Playgroud)
A2.c如下:
int i=0;
void func()
{}
Run Code Online (Sandbox Code Playgroud)
它编译得很好但是当我尝试链接这两个.o文件时,会出现"i的多重定义"错误.我理解i这里是一个全局变量,但它不需要extern在其他文件中使用关键字.在我的项目中,我没有使用extern.那怎么会出错呢?
这件事在 SO 的另一个问题中部分提到,但有点随意,因为这不是主要问题。由于我的困惑仍然存在,我将其放在一个单独的问题中。
为什么下面两个陈述相当于int* const p=&num而不是const int* p=&num后者看起来更符合逻辑和直观?造成这种行为的严格原因是什么typedef?
typedef int* PTR;
const PTR p=#
Run Code Online (Sandbox Code Playgroud)
最后,在该问题中,一位成员指出使用 ed 指针是不好的做法typedef。但我看到它在许多书籍和网站中被广泛使用,这似乎是一件很方便的事情。它使代码更容易理解。那么最终的结论是什么?是否应该typedef尽可能避免使用 ed 指针?
编辑:typedef如果我们打算执行以下操作,那么该语句的正确语法是什么:
const int* const p=#
Run Code Online (Sandbox Code Playgroud)
编辑:我无意中忘记问一件重要的事情。typedef那么使用该语句进行以下操作的正确语法是什么?
const int* p=# //instead of the int* const p=&num that we got
Run Code Online (Sandbox Code Playgroud)