ts101 #工作记录 #c/c++ #学习

构建一个 Hello World 项目 中我们分析到了编译器在编译的时候会使用到 -char-size-32 -double-size-32 来设置数据类型的大小.
在此我们对常用的数据类型大小进行检查和评估.

  • int short char long float double
  • struct 的大小分配问题

    未修改项目配置

    ```c typedef struct { char a; short b; int c; long d; long long e; double f; float g; } TestSize;

void testSizeOf() {

  1. printf("Test the sizeof for every type\n");
  2. printf("char: %d\n", sizeof(char));
  3. printf("short: %d\n", sizeof(short));
  4. printf("int: %d\n", sizeof(int));
  5. printf("long: %d\n", sizeof(long));
  6. printf("unsigned char: %d\n", sizeof(unsigned char));
  7. printf("unsigned short: %d\n", sizeof(unsigned short));
  8. printf("unsigned int: %d\n", sizeof(unsigned int));
  9. printf("unsigned long: %d\n", sizeof(unsigned long));
  10. printf("float: %d\n", sizeof(float));
  11. printf("double: %d\n", sizeof(double));
  12. printf("long double: %d\n", sizeof(long double));
  13. printf("TestSize: %d\n", sizeof(TestSize));

}

输出结果:<br />![image.png](https://cdn.nlark.com/yuque/0/2021/png/975505/1632810015281-84cc7fa5-3bbc-4a7e-a188-5c3c42db63e8.png#clientId=u900654a9-2a35-4&from=paste&id=u7ba4f39c&margin=%5Bobject%20Object%5D&name=image.png&originHeight=169&originWidth=283&originalType=binary&ratio=1&size=4917&status=done&style=none&taskId=u2caec111-72e6-4ce0-a15b-79dbc7d1d57)
<a name="AL8Gz"></a>
# 修改配置项

- 修改项目中char 类型为 8bits
- **Project -> Project Options -> Processor** , 设置为 8 bit

![image.png](https://cdn.nlark.com/yuque/0/2021/png/975505/1632834176594-adabfdf3-4662-42cc-978e-25542da06322.png#clientId=u26d542ab-ef6e-4&from=paste&height=339&id=u6db08c83&margin=%5Bobject%20Object%5D&name=image.png&originHeight=677&originWidth=876&originalType=binary&ratio=1&size=149945&status=done&style=none&taskId=u6f893e27-f4f8-4a7e-85ae-503a3febdb1&width=438)<br />运行之前的程序, 出现如下结果. 通过对内存分析可知,在 char 和 int 类型中都做了补零操作

Test the sizeof for every type char: 1 short: 2 int: 4 long: 4 unsigned char: 1 unsigned short: 2 unsigned int: 4 unsigned long: 4 float: 4 double: 4 long double: 8 TestSize: 32

![image.png](https://cdn.nlark.com/yuque/0/2021/png/975505/1632834730941-bb6d9f7f-9cad-4c0a-a7e1-a7a2e3e5f194.png#clientId=u26d542ab-ef6e-4&from=paste&height=29&id=u7a70b3c2&margin=%5Bobject%20Object%5D&name=image.png&originHeight=57&originWidth=503&originalType=binary&ratio=1&size=5488&status=done&style=none&taskId=u07f2b583-9364-49aa-92ea-92dc98143eb&width=251.5)

<a name="wd8tL"></a>
# 各种结构体的长度测试
下面我们对数据结构进行多次修改并看其长度

- 长度 8
```c
typedef struct {
    char a;
    short b;
    int c;
} TestSize;
typedef struct {
short a;
char b;
char c;
char d;
} TestSize;
  • 长度 4

    typedef struct {
      char a;
      short b;
    } TestSize;
    
    typedef struct {
    short a;
    char b;
    char c;
    } TestSize;
    
    typedef struct {
    char b;
    char c;
    } TestSize;
    
  • 长度12

    typedef struct {
      char a;
      short b;
      int c;
      long d;
    } TestSize;
    
  • 长度 16

    typedef struct {
      char a;
      short b;
      char z;
      int c;
      int d;
    } TestSize;
    
    typedef struct {
    long long a;
    long long b;
    } TestSize;
    
    typedef struct {
    long long a;
    int b;
    } TestSize;
    
    typedef struct {
    long long a;
    int b;
    int c;
    } TestSize;
    
  • 长度24

    typedef struct {
      char a;
      short b;
      int c;
      long d;
      long long e;
    } TestSize;
    
    typedef struct {
      char a;
      short b;
      int c;
      long long e;
      int d;
    } TestSize;
    
    typedef struct {
      char a;
      char z;
      short b;
      int c;
      long long e;
      int d;
    } TestSize;
    
    typedef struct {
    long long a;
    int b;
    int c;
    int d;
    } TestSize;
    
  • 长度 32

    typedef struct {
      char a; //  1, 2    [实际,占用]
      short b; // 2, 2
      char z; //   1,4
      int c; //    4,8
      long long e; // 8, 8
      int d; // 4,8
    } TestSize;
    

结论:

  • 使用 longlong 之后数据都是按照8字节对齐的,不够的地方会补 0 .
  • 使用 int, short,char 则是按照 4字节对齐, 在dsp 中最小的就 是 4字节这个不可以调整.
  • 根据我们的使用情况都是两个short 类型数据,可以采用4 字节对齐方式建立结构体方便取数据.

    研究开发手册调整对齐模式

  • Help -> Contents 打开帮助手册

image.png

  • Manuals -> Software Tool Manuals -> TigerSHARC … -> … -> Compiler -> C/C++ Compiler Language Extensions -> Pragmas -> Data Alignment Pragmas 讲述了如何控制对齐模式.
  • 下面有两个语法 ```c // 将下一行按照指定数字对齐 1 代表4 bit

    pragma align 4

pragma alignment_region (2)

<a name="GhRWS"></a>
## pragma align
> 下面是使用说明的译文

此 pragma 可在变量和字段声明之前使用。它适用于紧跟在 pragma 后面的变量或字段声明。pragma 的作用是将下一个变量或字段声明在 num 指定的边界上对齐。

- 如果将pragma应用于局部变量,则由于局部变量存储在堆栈上,因此只有当num不大于堆栈对齐(即4个字)时,才会更改变量的对齐方式。如果num大于堆栈对齐方式,则会发出警告,提示忽略pragma。
- 如果num大于以下变量或字段声明通常要求的对齐方式,则变量或字段声明的对齐方式将更改为num。
- 如果num小于通常需要的对齐方式,则变量或字段声明的对齐方式将更改为num,并发出警告,表示对齐方式已减少。
```c
typedef struct { 
    #pragma align 4 
    int foo; 
    int bar; 
    #pragma align 4 
    int baz; 
} aligned_ints;
  • 在本例中,任何声明为aligned_ints类型的对象的foo和baz成员都在四字边界上对齐。这个结构的大小是八个字,在bar和baz之间有两个未使用的字,在结构的末尾有三个填充字。在字节寻址模式下,要对齐的NUM参数必须是16而不是4,因为要对齐的参数是以可寻址单位表示的。

【在 8位 模式下这个 struct 还是 12 字节 及 3 个字, 下面是在 8位模式的测试, 也正好符合上面标红语句的内容】

typedef struct { 
    #pragma align 4 
    int foo; 
    int bar; 
    #pragma align 8
    int baz; 
} aligned_ints; 
// 长度 16

pragma alignment_region

这个只拷贝样例了, 这个由两个部分组成 alignment_region 和 alignment_region_end. 范围内的数据将都按照指定num进行对齐. 同样在 8位模式下 这个数字应该是 4 的整数倍.

#pragma align 4 
int aa;         /* alignment 4 */ 
int bb;         /* alignment 1 */ 
#pragma alignment_region (2) 
int cc;         /* alignment 2 */ 
int dd;         /* alignment 2 */ 
int ee;         /* alignment 2 */ 
#pragma align 4 
int ff;         /* alignment 4 */ 
int gg;         /* alignment 2 */ 
int hh;         /* alignment 2 */ 
#pragma alignment_region_end 
int ii;         /* alignment 1 */ 
#pragma alignment_region (1) 
long double jj;   /* alignment 1, but the compiler warns 
                      about the reduction */ 
#pragma alignment_region_end 
#pragma alignment_region (3) 
long double kk;   /* the compiler faults this, alignment is not 
                      a power of two */ 
#pragma alignment_region_end

不论如何修改还是长度为 24 字节, 即在 8字节处对齐, 结构体内尽量使用相同长度的数据类型进行定义, 方便使用功能


typedef struct {
#pragma align 4
    int b; // 4,4
#pragma align 4
    int c; // 4,4
#pragma align 4
    int d;// 4,8
    long long a; //8,8
} TestSize;

word 单位说明

一个 word 应该是 4 字节
当我这只 char 为 8 位时, num 代表的含义将是 1 字节

系统内建的数据类型

对系统内建的一些数据类型进行测试, 这样可以方便代码在不同c 程序之间的复用

printf("__uint8: %d\n", sizeof(__uint8));
printf("__uint16: %d\n", sizeof(__uint16));
printf("__uint32: %d\n", sizeof(__uint32));
printf("__uint64: %d\n", sizeof(__uint64));
printf("__int8: %d\n", sizeof(__int8));
printf("__int16: %d\n", sizeof(__int16));
printf("__int32: %d\n", sizeof(__int32));
printf("__int64: %d\n", sizeof(__int64));

定义自己的通用数据类型

下面是 types.h 文件定义的通用数据类型, 为后面的代码迁移提供便利

// 用于对库中的函数的公开性进行区分
#define PUBLIC
#define PRIVATE static

// 常用数据类型定义
typedef __uint8 UINT8;
typedef __uint16 UINT16;
typedef __uint32 UINT32;
typedef __uint64 UINT64;

typedef __int8 INT8;
typedef __int16 INT16;
typedef __int32 INT32;
typedef __int64 INT64;

struct 的大小说明

Within a structure, members of the fundamental types are aligned on a multiple of their size. Structures are aligned on the strictest alignment of any of their members, but are always aligned to at least 32 bits. As always, the size of a structure is a multiple of its alignment, so this last restriction leads to subtle differences from C implementations on Windows and UNIX® platforms. For example, struct A { short a; short b; short c; }; sizeof(struct A) // is 8 not 6 !!!. Entire variables are aligned to at least 32 bits. They are more strictly aligned if their type requires it. Entire array variables are aligned to 128 bits.

结构体必须按照 32bit 对齐