簡體   English   中英

指針數組的初始化

[英]Initialization of a pointer array

我在用指向結構成員的指針初始化數組時遇到問題。 必須通過結構指針訪問結構成員。 這樣做的原因是我們在運行時初始化了指向內存映射地址位置的指針。 以下代碼段是問題的一個示例;

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

typedef struct
{
  long* lp;
}T;

typedef struct
{
  long l;
}F;

F* f;

T t[] =
{
    { &f->l }
};

void init (void)
{
  f = (F*) 0x08000100; 
}

int main (void)
{
  init();

  return EXIT_SUCCESS;
}

編譯器輸出如下:

\n gcc -O0 -g3 -Wall -c\n -fmessage-length = 0 -osrc \\ Test.o .. \\ src \\ Test.c .. \\ src \\ Test.c:18: \n 錯誤:初始化元素不是恆定的\n .. \\ src \\ Test.c:18:錯誤:(在“ t [0] .lp”的初始化附近)\n .. \\ src \\ Test.c:18:錯誤:初始化元素不是恆定的\n .. \\ src \\ Test.c:18:錯誤:(在t [0]的初始化附近) \n 發生構建錯誤,構建已停止\n

這里的問題是我們在運行時初始化指針,編譯器不知道在哪里可以找到結構成員。 我們無法解決結構指針,因為我們不想為此使用鏈接程序腳本。

任何想法如何解決這個問題?

T t[] =
{
    { &f->l }
};

元素的地址(例如&f-> l)僅在運行時知道。

這樣的值不能用於編譯時初始化(這是在此處進行的操作)。

t []數組要等到運行時才能填寫-因為直到運行時才知道F的地址。

您可以將T []初始化為{NULL}並在初始化后對其進行修補。

另一種方法是將T的成員初始化為只是結構內的偏移量,然后在初始化f之后,遍歷數組並通過添加f的地址來調整指針位置。 此技術類似於鏈接中經常使用的技術。

像這樣:

#define MEMBER_OFFSET_OF(a,b) &(((a*)0)->b)

T t[] = 
{
   {(long*)MEMBER_OFFSET_OF(F, l)}
};
const int numElementsInT = sizeof(t) / sizeof(t[0]);

void init()
{
 f = (F*) 0x08000100; 
 for (int i= 0; i < numElementsInT; i++)
 {
   t[i].lp += (unsigned int)f;
 }  
}

從技術上講,對於C90編譯器而言,這是無法解決的。 對於初始化習語,

聲明符 = 初始化序列

初始化序列必須是一個常量表達式,即可以在編譯時或鏈接時計算的一個常量表達式。 所以,

int a;
int *b[] = { &a };

工作,而

void foo() {
    int a;
    int *b[] = { &a };
}

不會因為在運行時之前無法計算自動地址a的地址。

如果切換到C99,則后者可以使用。 但是,您的代碼仍然超出了C99編譯器可以預計算的范圍。 如果切換到C ++,您的代碼將正常運行,至少Comeau不反對。 編輯:Roger當然是正確的,因為這不能解決通過NULL指針進行不正確的取消引用的問題。

假設您可以使用非恆定數據初始化全局變量:您仍然遇到很大的問題。

當t初始化時,f仍然具有不確定的值:這發生 init()執行並分配魔術地址之前。 因此,即使您可以使用&f->l ,也無論如何都必須重置它的所有使用位置。

暫無
暫無

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

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