令你感到迷惑的C问题

No1

以下C程序的预期输出是打印数组中的元素。 但是当实际运行时,它不会这样做

#include<stdio.h>
#define TOTAL_ELEMENTS (sizeof(array) / sizeof(array[0]))
int array[] = {23, 34, 12, 17, 204, 99, 16};
int main()
{
    int d;
    for(d = -1; d <= (TOTAL_ELEMENTS-2); d++)
        printf("%d\n", array[d + 1]);
    return 0;
}

它看起来似乎没有问题,但当你运行的时候会出现以下的说明

comparison of integer expressions of different signedness: ‘int’ and
‘long long unsigned int’ [-Wsign-compare]

翻译以下:有符号性的整数表达式的比较:“ int”和“ long long unsigned int” [-Wsign-compare]
d <= (TOTAL_ELEMENTS-2)dint型,TOTAL_ELEMENTSlong long unsigned int型,虽然为警告信息,但程序却输出不了任何内容

NO2

下面的程序是一个完美的C程序。但是在编译时,却存在一个愚蠢的错误

#include<stdio.h>
void OS_Solaris_print()
{
    printf("Solaris - Sun Microsystems\n");
}
void OS_Windows_print()
{
    printf("Windows - Microsoft\n");
}
void OS_HP-UX_print()
{
    printf("HP-UX - Hewlett Packard\n");
}
int main()
{
    int num;
    printf("Enter the number (1-3):\n");
    scanf("%d",&num);
    switch(num)
    {
        case 1:
            OS_Solaris_print();
            break;
        case 2:
            OS_Windows_print();
            break;
        case 3:
            OS_HP-UX_print();
            break;
        default:
            printf("Hmm! only 1-3 :-)\n");
        break;
	}
	return 0;
}

错误void OS_HP-UX_print()OS_HP-UX_print()的表达出现了不应该的符号-,切记,切记在C语言中-不可以出现,除了注释

No3

以下程序的预期输出是多少?为什么?

#include<stdio.h>
enum {false,true};
int main()
{
    int i=1;
    do
    {
        printf("%d\n",i);
        i++;
        if(i < 15)
            continue;
    }while(false);
    return 0;
}

代码解释:枚举是 C 语言中的一种基本数据类型,它可以让数据更简洁,更易读。枚举语法定义格式为:enum 枚举名 {枚举元素1,枚举元素2,……},如果没有enum {false, true}do{}while(false)将会报错
输出:1 解释:do{}while语句先执行后做判断

NO4

下面的程序“似乎”不会打印“hello-out”

#include <stdio.h>
#include <unistd.h>
int main()
{
	while(1)
	{
		fprintf(stdout,"hello-out");
		fprintf(stderr,"hello-err");
		sleep(1);
	}
	return 0;
}

执行程序,得到下面的结果

hello-out hello-err hello-out hello-err hello-out hello-err 。。。

为什么?我不清楚

NO5

仅通过查看程序,您“可能”会期望输出是相同的,这两个printf语句也是如此

#include <stdio.h>
#define f(a,b) a##b
#define g(a) #a
#define h(a) g(a)
int main()
{
    printf("%s\n", h(f(1, 2)));
    printf("%s\n", g(f(1, 2)));

    return 0;
}

但是实际的输出却是

12
f(1, 2)

解释说明:C语言中,a##b表示将a和b连接起来,#a是将a字符串化。在类似函数的宏中出现的参数(除非它是#或##的操作数)会在替换它并重新扫描整个以进行进一步扩展之前进行扩展。因为g的参数是#的操作数,所以参数不会展开,而是立即被字符串化(“f(1,2)”)。因为h的参数不是#或者##的操作数,所以首先扩展参数(12),然后替换(g(12)),然后重新扫描并进一步扩展(“12”)

NO6

您认为下面程序的输出是什么?为什么?

#include <stdio.h>
int main()
{
    float f = 0.0f;
    int i;
    for(i = 0; i < 10; i++)
        f = f + 0.1f;
    printf("%f", f);
    if(f == 1.0f)
        printf("f is 1.0 \n");
    else
        printf("f is NOT 1.0\n");
    return 0;
}

程序输出:1.000000f is NOT 1.0。这是计算机中浮点数机制导致的,浮点数是一个麻烦的Thing

NO7

我认为下面的C程序是完全有效的(在阅读了C中的逗号操作符之后)。
但是下面的程序有错误,你能找出来吗?

#include <stdio.h>
int main()
{
    int a = 1, 2;
    printf("a : %d\n", a);
    return 0;
}

解释说明:int a = 1, 2会有错误的表示,正确的大概应该是这样子int a, b = 2

NO8

下面的C程序的输出是什么?(它是有效的C程序吗?)

#include <stdio.h>
int main()
{
    int i = 43;
   	printf("%d\n", printf("%d", printf("%d", i)));
    return 0;
}

解释说明:首先执行括号最里面的printf("%d", i),执行结果是43,此时printf("%d", i)的值是2,因为printf()函数的返回值是是输出的字符个数,输出"4"和"3"两个字符,所示printf("%d", i)的值是2,printf("%d", printf("%d", i))输出的是2,只有"2"这一个字符,所以printf("%d\n", printf("%d", printf("%d", i)))输出的1

NO9

下面的两个函数原型一样吗?

int foobar(void);
int foobar();

不一样,foobar(void)的参数必须是空(void),foobar()的参数可有可无

NO10

以下程序的输出是什么?为什么?

#include <stdio.h>
int main()
{
    float a = 12.5;
    printf("%d\n", a);
    printf("%d\n", (int)a);
    printf("%d\n", *(int *) &a);
    return 0;
}

程序输出

0
12
1095237632

解释说明:浮点数是4个字节,12.5f 转成二进制是:01000001010010000000000000000000,十六进制是:0x41480000,十进制是:1095237632

首先:float和double的内存布局,如下:
float: 1位符号位(s)、8位指数(e),23位尾数(m,共32位)
double: 1位符号位(s)、11位指数(e),52位尾数(m,共64位)

然后:printf由于类型不匹配,所以会把float直接转成double,注意,12.5的float和double的内存二进制完全不一样。

接着:在x86芯片下使用是的反字节序,高位字节和低位字位要反过来

所以12.5的双版本表示如下:
float版:0x41480000 (在内存中是:00 00 48 41)
double版:0x4029000000000000 (在内存中是:00 00 00 00 00 00 29 40)

%d要求是一个4字节的int,对于double的内存布局,我们可以看到前四个字节是00,所以输出自然是0了

额外的:这个示例说明了printf并不是类型安全的,这就是为C++要引入cout的原因了

NO11

解释以下C程序的输出(输出b不是20)

#include<stdio.h>
int main()
{
    int a = 1;
    switch(a)
    {
        int b = 20;
        case 1: printf("b is %d\n", b);
            break;
        default:printf("b is %d\n", b);
            break;
    }
    return 0;
}

解释说明:

switch(a)
    {
        int b = 20; //此语句被跳过不执行
        case 1: printf("b is %d\n", b);
            break;
        default:printf("b is %d\n", b);
            break;
    }

switch-case语句会跳过switch与case之间的语句

NO12

以下程序的输出是什么?(同样,它不是40(如果整数的大小是4))

#include<stdio.h>
#define SIZE 10
void size(int arr[SIZE])
{
    printf("Size of array is:%d\n", sizeof(arr));
}

int main()
{
    int arr[SIZE];
    size(arr);
    return 0;
}

解释说明:C语言下,sizeof的可能大小

short x
sizeof(float)          = 4
sizeof(void(*)(void))  = 8
sizeof(char[10])       = 10
sizeof 'a'             = 4
sizeof &main           = 8
sizeof "hello"         = 6
sizeof x               = 2
sizeof (x+1)           = 4

arr表示数组的首地址,地址的大小就是8

NO13

下面的C程序有什么潜在问题?

#include <stdio.h>
int main()
{
	char str[80];
	printf("Enter the string:");
	scanf("%s", str);
	printf("You entered:%s\n", str);
	return 0;
}

潜在问题1:输入了超过80个长度的字符,那么就会有数组越界的问题了,程序很有可以会崩溃;潜在问题2:输入的字符串有空格等一些字符,那么程序的只输出空格等这些字符之前的字符,比如Hello World程序输出的是Hello

NO14

下面的程序的输出是什么?

#include <stdio.h>
int main()
{
	int i;
	i = 10; //i初始化为10
	printf("i : %d\n", i); //打印i : 10
	printf("sizeof(i++) is: %d\n", sizeof(i++)); //int类型的sizeof为4
	printf("i : %d\n", i); //i=10,不是i=11
	return 0;
}

解释说明:第三个为什么输出的不是11,而是10呢原因是,sizeof不是一个函数,是一个操作符,其求i++的类型的size,这是一件可以在程序运行前(编译时)完全的事情,所以sizeof(i++)直接就被4给取代了,在运行时也就不会有了i++这个表达式

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值