簡體   English   中英

C99 復雜類型二進制文件是否與具有兩個成員的結構兼容?

[英]Is a C99 complex type binary compatible with a structure with two members?

我可以使用typedef struct {double r; double i;} DC; typedef struct {double r; double i;} DC; 作為 C99 double complex類型的二進制兼容數據類型?

我的實驗性 C 代碼適用於我的情況(gcc / x86-64 / Linux)。 但這是否普遍有效

/* gcc -o test test.c (WORKS) */
/* gcc -O3 -march=native -o test test.c (WORKS with volatiles) */

#include <stdio.h>
#include <stdlib.h>
#include <complex.h>

typedef struct {
    double r;
    double i;
} DC;

int main()
{
    /* var */
    const int N = 3;

    volatile DC *c = malloc(N*sizeof(DC));

    volatile double complex *z;
    z = (double complex *) c;

    int i;

    /* init */
    for(i=0; i<N; i++)
    {
       c[i].r = (double) i+1;
       c[i].i = (double) (i+1) * 10;
    }
    z[1] = -0.1 -0.2*I; // THE POINT IS HERE

    /* results */
    for(i=0; i<N; i++)
    printf("i = %d, c[i].r = %f c[i].i = %f\n", i, c[i].r, c[i].i);

    /* end */
    free((void*) c);

    return 0;
}

程序的輸出在這里:

i = 0, c[i].r = 1.000000 c[i].i = 10.000000
i = 1, c[i].r = -0.100000 c[i].i = -0.200000
i = 2, c[i].r = 3.000000 c[i].i = 30.000000

我發現用於測試 gcc 是否會識別兩種類型之間的別名最可靠的模式示例如下:

#include <complex.h>
typedef struct  { double r,i; } d2;

double test(double complex *cd, d2 *dd)
{
  if (dd->r)
    *cd = 1.0;
  return dd->r;
}

gcc 7.1 生成的代碼是

.LC1:
        .long   0
        .long   1072693248
        .long   0
        .long   0
test:
        movsd   xmm0, QWORD PTR [rsi]
        ucomisd xmm0, QWORD PTR .LC0[rip]
        jp      .L4
        je      .L1
.L4:
        movsd   xmm1, QWORD PTR .LC1[rip]
        movsd   QWORD PTR [rdi], xmm1
        movsd   xmm1, QWORD PTR .LC1[rip+8]
        movsd   QWORD PTR [rdi+8], xmm1
.L1:
        rep ret
.LC0:
        .long   0
        .long   0

函數的返回值在 xmm0 中,它從 dd->r 加載並針對零進行測試。 如果它不為零,則代碼將新值存儲到 *cd,但不會重新加載 xmm0 中的值。

我不確定標准的作者為了什么目的指定了復數的存儲方式,因為他們並沒有使它們與其他任何東西別名兼容,但是 gcc 更重視標准沒有強制要求的事實它識別別名而不是能夠為布局兼容的類型別名是有用的這一事實。

是的,我的 C11 標准副本說(我假設 C99 說相同):

每個復數類型與包含對應實數類型的兩個元素的數組類型具有相同的表示和對齊要求; 第一個元素等於復數的實部,第二個元素等於復數的虛部。

假設在成員之間或之后沒有添加填充(因為它很可能不會添加),則您的struct_Complex double二進制兼容。

顯然,關鍵字是“假設”,這意味着並非普遍有效。 因此,上述文本來自標准。

如果你想要普遍有效,你會想要使用:

double val[2]; // double _Complex

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM