C/C++零碎知识点

本文整理了C/C++编程中的一些易忽视知识点,包括printf()函数的参数压栈顺序,类型转换与浮点数表示,运算符优先级与位操作,结构体内存对齐规则,以及sizeof运算符的应用实例分析。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

记录点自己阅读过程中看到的一些不曾注意到的知识点,有空时看看,可以复习复习

1. printf()函数

#include "stdafx.h"

int _tmain(int argc, _TCHAR* argv[])
{
    int b = 3;
    int array[] = {6,7,8,9,10};
    int *ptr = array;
    *(ptr ++) += 123;
    printf("%d %d\n",*(ptr),*(++ptr));

    return 0;
}

上面这段代码输入出的正确结果应该是8 8.

-分析:

  1. (ptr ++) += 123.先执行(ptr) += 123,然后ptr++
  2. printf()函数在计算参数时是从右到左进行压栈的,所以printf(“%d %d\n”,(ptr),(++ptr));是从右到左进行运算,先ptr++,然后再输出(ptr),(ptr).

2. 类型转换及浮点数的表示

#include <iostream>

using namespace std;

int main()
{
    float a = 1.0f;
    cout << boolalpha << ( (int)a == (int&)a ) << endl;

    float b = 0.0f;
    cout << boolalpha << ( (int)b == (int&)b ) << endl;

    return 0;
}

这段代码的输出应该是:

false
true

-分析:

  • (int&)a 相当于将该浮点数地址开始的sizeof(int)个字节当成int型数值输出
  • 浮点数在内存中的表示方法和整型不同,1.0f在内存中实际上并不是1.这部分的详细解析可以先参考这个博主的分析,后续自己会补偿完整点击这里跳转

3. 运算符问题

#include <iostream>

using namespace std;

int main()
{
    unsigned char a = 0xA5;
    unsigned char b = ~a >> 4 + 1;

    printf("%d\n",b);

    return 0;
}

这段代码的输出应该是 250

分析:
进入汇编命令下,可以看到,编译器先进行取反操作后进行移位操作,移位之前进行了加法运算,因此移位5位。此外,还有个要点是eax是16位的寄存器,所以转化时要按16位进行运算。
汇编命令


4. sizeof/底层机制

#include <iostream>

using namespace std;

struct{
    short a1;
    short a2;
    short a3;
}A;
struct{
    long a1;
    short a2;
}B;

int main()
{
    char *ss1 = "0123456789";
    char ss2[] = "0123456789";
    char ss3[100] = "0123456789";
    int ss4[100];
    char q1[] = "abc";
    char q2[] = "q\n";
    char *q3 = "a\n";

    char *str1 = (char *)malloc(100);
    void *str2 = (void *)malloc(100);

    cout << sizeof(ss1) << " ";
    cout << sizeof(ss2) << " ";
    cout << sizeof(ss3) << " ";
    cout << sizeof(ss4) << " ";
    cout << sizeof(q1) << " ";
    cout << sizeof(q2) << " ";
    cout << sizeof(q3) << " ";
    cout << sizeof(A) << " ";
    cout << sizeof(B) << " ";
    cout << sizeof(str1) << " ";
    cout << sizeof(str2) << " ";

    cout << endl;

    return 0;
}

这段代码的正确输出结果应该是:
4 11 100 400 4 3 4 6 8 4 4

-分析:

  • sizeof是C/C++中的一个操作符(operator),简单的说其作用就是返回一个对象或者类型所占的内存字节数。
  • 指针的大小是一个固定值,为4
  • 1个字符所占空间大小为1字节,1个整型变量所占空间大小为4字节
  • 结构体长度一定是最长数据元素的整数倍。如果结构体内存在长度大于处理器位数的元素,那么就以处理器的位数为对齐单位。
  • 上述A的对齐方式如下:(以32位机器为例子)
    |-a1-|-a2-| 4位
    |-a3-| 2位
    总共6位,6%2 == 0所以满足
    对于B:
    |–a1–| 4位
    |-a2-| 2位
    总共6为,6%4 != 0,内存补齐为8

5.sizeof问题2

#include <iostream>
#include <string>

using namespace std;

int f1(){return 1;}

int main()
{

    int a = 5;
    cout << sizeof(a = 6) << endl;
    cout << a << endl;

    int b[] = {1,2,3};
    cout << sizeof(b) << endl;

    int *c = new int[3];
    cout << sizeof(c) << endl;

    cout << sizeof(f1()) << endl;

    return 0;
}

这段代码的正确输出应该为:
4
5
12
4
4

-分析:

  • sizeof不是函数也不是一元运算符,是个类似于宏定义的特殊关键字,sizeof()括号中的内容在编译时是不被编译的,而是直接替换。如int a;sizeof(a)其实就等价于sizeof(int),括号内的操作不被编译
  • 对函数使用sizeof(),其值根据函数返回值类型确定
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值