3


1

32〜64ビット用に書かれたCソースコードの移植

64ビットに移植しようとしているCソースコードは、32ビット環境で警告なしに実行されます。 compile gcc(Ubuntu 4.4.1-4ubuntu9)4.4.1を使用して64ビットLinux環境でコンパイルすると、主に次の警告が表示されます。

warning: cast to pointer from integer of different size

上記の警告が最も多かった。 * uintptr_t タイプを使用し、それらの警告のほとんどは削除されました。 * int / unsigned int *を uintptr_t *を使用して64ビットに変更できます。 しかし、64ビットと互換性を持たせるために、次のタイプをどのように変更できますか?

typedef void*  POINTER;

次のコードを変更しました。

typedef unsigned int    ABC;

into

typedef uintptr_t ABC

次の警告が表示されました。

warning: passing argument 2 of ‘function’ from   incompatible pointer type
note: expected ‘ABC *’ but argument is of type ‘unsigned int *’

さらに、以前のintまたはunsigned intであったタイプdefをuintptr_tに変更した後、次のようにほとんどの警告が発生します。

warning: inlining failed in call to ‘abc_StringCopy’: call is unlikely and code size would grow

関数tptp_StringCopyは次のとおりです。

static __inline__ char* abc_StringCopy(void)
{
  char *copy;
  copy = (char*)Malloc(yyleng+1);
  strcpy(copy, yytext);
  return copy;

これらの警告を取り除くにはどうすればよいですか?

4 Answer


2


64ビットシステムでは、「unsigned int」は「uintptr_t」と互換性がありません。 int`と unsigned int`は、64ビットマシンでは32ビット値のままですが、 `uintptr_t`は64ビットタイプになります。 型が `uintptr_t`と呼ばれる理由は、型がポインターと同じ幅の符号なし整数値だからです。 つまり、uintptr_tは32ビットマシンでは32ビット幅ですが、64ビットマシンでは64ビット幅になります。

コードでは、これは、 typedef`の変更により、64ビットマシンでは NAT * は64ビット変数への64ビットポインターですが、 unsigned int * `は64ビットポインターへの32ビット変数。

「clause_ComputeSplitFieldAddress」はまだ「unsigned int *」パラメーターを想定しています。


1


ここでの根本的な問題は、ポインターが損失なく32ビット整数型との間でキャストできることを想定していることだと思います。 32ビットコードではこれは当てはまりますが、64ビットコードではそうではありません。ポインターは64ビットタイプです。 これはおそらく、最も一般的な32ビットから64ビットへの移植の問題です。

NATの実際の意図は何ですか? 構造体への不透明なポインター(32ビットコードでは32ビット整数としてドレスアップ)である場合、uintptr_tではなくvoid *として宣言するのが最適です。


1


POINTER typedefを変更する明確な理由はありません。 voidポインターは、32ビットと64ビットの両方で引き続きvoidポインターです(ただし、32ビットバージョンは64ビットバージョンの半分のスペースを占有します)。 POINTERを悪用し、それを何らかの整数として扱うことを試みた場合にのみ、問題が発生します。

Clause_ComputeSplitFieldAddressのコードは表示しませんが、関数が 'NAT *'をとる場合、明らかに 'unsigned int’のアドレスを渡すことはできません。それが呼び出される場所を見て、呼び出し元のコードを修正する適切なアクションを決定する必要があります-基本的に、関連するunsigned int変数をNAT変数に変更します。

tptp_StringCopy関数では、おそらく `strdup()`を使用する必要があります。メモリ割り当てが失敗してもすぐにクラッシュすることはないでしょう。

List_Cons()に関連する警告は表示されないため、すぐに解決することはできません。

一般的に、整数とポインターの間で型の整理を行わないようにすることで、32ビットから64ビットの問題の多くに対処できます。 必要な場合は、uintptr_t(および ``)を使用します。 また、特定のtypedef名の変数型定義がある場合は、「で厳密に定義された印刷およびスキャン形式を使用します。 例えば、

PRIXPTR

uintptr_t値をフォーマットするには:

printf("0x%08" PRIXPTR "\n", ptr_as_int);

これはすべての問題に対処するわけではありません。それらの多くに対処します。

コンパイラは、インライン化されていないコードについて知りたい場合に警告する権利があります。 インライン化できない関数のインライン化を要求しないことを除いて、それについてできることはあまりありません。


-1


状況については明確ではありませんが、「unsigned int」を「uintptr_t」に変更したようです。 前者はunsigned int、後者はunsigned int _pointer_です。

一般に、これは有効な置換ではありません。

また、コードは「32ビットで警告なしで実行される」と言いましたが、64ビットでコンパイルすると警告が表示されます。 しかし、警告なしに実行されるかどうかは実際には関係ありません。 おそらく、警告なしにコンパイルされます。 本当? 変更したコードは、警告なしで32ビット用にコンパイルされますか? それは驚きです。