C语言中#pragma pack(1)的用法与注意点

目录
  • 一:何时使用
  • 二. 为什么使用#pragma pack(1)
  • 三.注意点
  • 四.#pragma pack()的一些用法
  • 五.题目
  • 附:C语言慎用#pragma pack(1)命令
  • 总结

一:何时使用

#pragma pack(1)的用法大多是用在结构体中

二. 为什么使用#pragma pack(1)

结构体的字节对齐方式在不同的编译器中不同,会存在数据冗余,以下举个例子

 struct example
    {
        char header_start;
        double data_type;
    };

现有的结构体,就会按照结构体成员中最大的数据类型对齐,例子当中就是double型,按照8个字节进行对齐。那么此时sizeof(example)就是16,存在7个空字节,因为其中char只占一个字节

如果加上#pragma pack(1),那么example按1个字节对齐方式对齐,此时sizeof(example)就是等于9

三.注意点

这种方法的使用一定要是成对使用,如下面例子

#pragma pack(1)
struct example
    {
        char header_start;
        double data_type;
    };
#pragma pack()

我们一定要在结构体末尾加上#pragma pack()进行取消自定义字节对齐的命令,如果不取消,可能会导致整个程序存在问题。因为会影响到其他的结构体对齐方式

四.#pragma pack()的一些用法

#pragma pack(show) //显示当前内存对齐的字节数,编辑器默认8字节对齐

#pragma pack(n) //设置编辑器按照n个字节对齐,n可以取值1,2,4,8,16

#pragma pack(push) //将当前的对齐字节数压入栈顶,不改变对齐字节数

#pragma pack(push,n) //将当前的对齐字节数压入栈顶,并按照n字节对齐

#pragma pack(pop) //弹出栈顶对齐字节数,不改变对齐字节数

#pragma pack(pop,n) //弹出栈顶并直接丢弃,按照n字节对齐

五.题目

牛牛需要建立一个结构体Nowcoder,该结构体包括三个成员,其类型分别是int、double和char。假设牛牛想让这个结构体所占据的内存最小,请问你该怎么建立该结构体?(输入三个相应类型的变量用于初始化结构体)

示例1

输入:1,1.000,a
返回值:13

代码

/**
 * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
 *
 *
 * @param n int整型
 * @param d double浮点型
 * @param c char字符型
 * @return int整型
 */

 #pragma pack(1)
struct Nowcoder{
    char c;
    int n;
    double d;
};

int smaller_space(int n, double d, char c ) {
    // write code here
    struct Nowcoder temp;
    temp.c=c;
    temp.n=n;
    temp.d=d;
    return sizeof(temp);
}

附:C语言慎用#pragma pack(1)命令

在我们在按字节传输一些数据的时候,肯定会定义一些结构体,但是结构体的字节对齐方式可能在不同的编译器中不一样,这样会在数据传输过程中增加冗余的数据。

为了方便数据传输,我们可以用#pragma pack(1)命令,将结构体里的变量强制进行1字节对齐,但是我们在用完这个命令后,一定要在定义的数个结构体后加一个取消自定义字节对齐的命令:#pragma pack(),如果不取消就可能导致整个程序都会有问题,因为这个命令会影响到其它的结构体的字节对齐方式,但并不会全部全部影响(推测)。正确用法是:

#pragma pack(1)

typedef struct
{

.......
} xxxxx;

typedef struct
{

.......
} xxxxx;

........

#pragma pack()

总结

到此这篇关于C语言中#pragma pack(1)的用法与注意点的文章就介绍到这了,更多相关C语言#pragma pack(1)用法内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 浅谈C语言的字节对齐 #pragma pack(n)2

    #pragma pack(n) 这是给编译器用的参数设置,有关结构体字节对齐方式设置, #pragma pack是指定数据在内存中的对齐方式. #pragma pack (n)             作用:C编译器将按照n个字节对齐. #pragma pack ()               作用:取消自定义字节对齐方式. #pragma  pack (push,1)     作用:是指把原来对齐方式设置压栈,并设新的对齐方式设置为一个字节对齐 #pragma pack(pop)      

  • C语言中#pragma pack(1)的用法与注意点

    目录 一:何时使用 二. 为什么使用#pragma pack(1) 三.注意点 四.#pragma pack()的一些用法 五.题目 附:C语言慎用#pragma pack(1)命令 总结 一:何时使用 #pragma pack(1)的用法大多是用在结构体中 二. 为什么使用#pragma pack(1) 结构体的字节对齐方式在不同的编译器中不同,会存在数据冗余,以下举个例子 struct example { char header_start; double data_type; }; 现有的

  • C语言中的const和free用法详解

    注意:C语言中的const和C++中的const是有区别的,而且在使用VS编译测试的时候.如果是C的话,请一定要建立一个后缀为C的文件,不要是CPP的文件.因为,两个编译器会有差别的. 一.C语言中的const比较常见的用法,const做常量 #include<stdio.h> #include<malloc.h> #include<string.h> /* C中的const用法(使用VS测试的时候,要注意建立一个C后缀的文件,因为C的编译器和C++的编译器还是有区别的

  • 详解C++语言中std::array的神奇用法

    概述 std::array是在C++11标准中增加的STL容器,它的设计目的是提供与原生数组类似的功能与性能.也正因此,使得std::array有很多与其他容器不同的特殊之处,比如:std::array的元素是直接存放在实例内部,而不是在堆上分配空间:std::array的大小必须在编译期确定:std::array的构造函数.析构函数和赋值操作符都是编译器隐式声明的--这让很多用惯了std::vector这类容器的程序员不习惯,觉得std::array不好用.但实际上,std::array的威力

  • 详解C语言中typedef和#define的用法与区别

    目录 一.typedef的用法 二.#define的用法 三.typedef与#define的区别 四.typedef的用途 用途一 用途二 用途三 用途四 五.typedef的陷阱 陷阱一 陷阱二 一.typedef的用法 在C/C++语言中,typedef常用来定义一个标识符及关键字的别名,它是语言编译过程的一部分,但它并不实际分配内存空间,比如: typedef int INT; typedef (int*) pINT; typedef unsigned int uint32_t type

  • C语言中的switch语句基本用法

    switch语句: 实际生活中,需要做出很多选择,大家都知道做选择可以使用if语句,但是如果选择太多,if语句使用起来就会很繁琐,这个时候就需要一个能将代码简化的语句,也就是我们今天的主角switch语句. switch语句是一个多分支选择语句,并且可以支持嵌套. switch语句的基本格式 switch(表达式) { case 常量1:语句1 case 常量2:语句2 default:语句n break; } switch语句通过将表达式的值与常量值进行比对,如果相等则执行后面的语句,如果不相

  • C语言中#pragma once的作用

    目录 1.#pragma once有什么作用? 2.两者的使用方式有何区别? 3.两者各有何特点? (1)#ifndef (2)#pragma once 4.两者之间有什么联系? 1.#pragma once有什么作用? 为了避免同一个头文件被包含(include)多次,C/C++中有两种宏实现方式:一种是#ifndef方式:另一种是#pragma once方式. 在能够支持这两种方式的编译器上,二者并没有太大的区别.但两者仍然有一些细微的区别. 2.两者的使用方式有何区别? 示例代码如下: /

  • c语言中static和extern的用法详细解析

    一,static和extern:大工程下我们会碰到很多源文档. 文档a.c 复制代码 代码如下: static int i; //只在a文档中用int j;    //在工程里用static void init()         //只在a文档中用{}void callme()          //在工程中用{   static int sum;} 上面的全局i变量和init()函数只能用在a.c文档中,全局变量sum的作用域只在callme里.变量j和函数callme()的全局限扩充到整个

  • 聊聊R语言中Legend 函数的参数用法

    如下所示: legend(x, y = NULL, legend, fill = NULL, col = par("col"), border = "black", lty, lwd, pch, angle = 45, density = NULL, bty = "o", bg = par("bg"), box.lwd = par("lwd"), box.lty = par("lty")

  • 简介Go语言中的select语句的用法

    在Go编程语言中的select语句的语法如下: 复制代码 代码如下: select {     case communication clause  :        statement(s);          case communication clause  :        statement(s);     /* you can have any number of case statements */     default : /* Optional */        stat

  • C语言中const,volatile,restrict的用法总结

    1. const 变量声明中带有关键词const,意味着不能通过赋值,增量或减量来修改该变量的值,这是显而易见的一点.指针使用const则要稍微复杂点,因为不得不把让指针本身成为const和指针指向的值成为const区别开来.下面的声明表示pf指向的值必须是不变的 constfloat *pf:而pf则是可变的,它可以指向另外一个const或非const值:相反,下面的声明说明pf是不能改变的,而pf所指向的值则是可以改变的: float* const pf: 最后,当然可以有既不能改变指针的值

随机推荐