X
などのデータ型があり、その型の変数またはポインターを宣言せずに、もちろんsizeof
演算子を使用せずに、そのサイズを知りたいです。
これは可能ですか?データ型のサイズと範囲を含む標準のヘッダーファイルを使用することを考えましたが、ユーザー定義のデータ型では機能しません。
私の考えでは、これは「++、+ =、または+を使用せずに2つのintを追加するにはどうすればよいですか?」というカテゴリに当てはまります。それは時間の無駄です。このようなことをすることで、未定義の振る舞いのモンスターを避けようとすることができます。
size_t size = (size_t)(1 + ((X*)0));
declareX
への型またはポインタの変数ではないことに注意してください。
ほら、sizeof
isこのための言語機能。唯一のものなので、これを達成するための唯一のポータブルな方法です。
いくつかの特別なケースでは、特定のオブジェクトのサイズを理解するために他のヒューリスティックを使用する移植性のないコードを生成できます[*](おそらくオブジェクトが自分のサイズを追跡するようにすることによって)が、すべての簿記を自分で行う必要があります。
[*] OOPの意味ではなく、非常に一般的な意味のオブジェクト。
ええと、私はアマチュアです。しかし、私はこの問題を試し、sizeofを使用せずに正しい答えを得ました。これがお役に立てば幸いです。私は整数のサイズを見つけようとしています。
int *a,*s, v=10;
a=&v;
s=a;
a++;
int intsize=(int)a-(int)s;
printf("%d",intsize);
このインタビューの質問に対する正解は、「sizeof()が私のためにそれを行うのに、なぜそれをしたいのか、そしてそれを行う唯一の移植可能な方法なのか?」です。
パディングの可能性は、それを導入するために使用されるルールの知識がなければ、すべての希望を防ぎます。そして、それらは実装に依存します。
これを試して:
int a;
printf("%u\n", (int)(&a+1)-(int)(&a));
特定のプロセッサの [〜#〜] abi [〜#〜] を読んで、パズルを解くことができます。これは、構造がメモリ内にどのように配置されているかを説明しています。プロセッサごとに異なる可能性があります。しかし、コンパイラーを作成しているのでない限り、この問題を解決するための1つの正しい方法であるsizeof
だけを使用したくないのは驚くべきことです。
xがデータ型の場合:
#define SIZEOF(X) (unsigned int)( (X *)0+1 )
xが変数の場合:
#define SIZEOF(X) (unsigned int)( (char *)(&X+1)-(char *)(&X) )
コンパイラのソースを調べます。あなたが得るでしょう:
そしてこれから、何でも予想されるサイズ。
少なくとも変数にスペースを割り当て、それにセンチネル値を入力できれば、少しずつ変更して値が変更されるかどうかを確認できますが、それでもパディングに関する情報はわかりません。
これを試して:
#include<stdio.h>
int main(){
int *ptr = 0;
ptr++;
printf("Size of int: %d",ptr);
return 0;
ユーザーコードでC89ソリューション以降で利用可能:
sizeof
演算子を使用しない。@ steve jessop で示唆されているように、標準コードを使用するのは簡単です。
offsetof(type, member-designator)
これは、タイプ
size_t
の整数定数式に展開され、その値はバイト単位のオフセットであり、構造体の先頭から構造体メンバー...に展開されます...C11§7.193
#include <stddef.h>
#include <stdio.h>
typedef struct {
X member;
unsigned char uc;
} sud03r_type;
int main() {
printf("Size X: %zu\n", offsetof(sud03r_type, uc));
return 0;
}
注:このコードは"%zu"
を使用しており、C99以降が必要です。
これがコードです。トリックは、ポインタオブジェクトを作成し、そのアドレスを保存し、ポインタをインクリメントしてから、前のアドレスから新しいアドレスを減算することです。重要な点は、ポインタがインクリメントされるとき、実際にはそれが指しているオブジェクトに等しいサイズで移動することです。したがって、ここではクラスのサイズ(それが指しているオブジェクト)です。
#include<iostream>
using namespace std;
class abc
{
int a[5];
float c;
};
main()
{
abc* obj1;
long int s1;
s1=(int)obj1;
obj1++;
long int s2=(int)obj1;
printf("%d",s2-s1);
}
よろしく
これを行う簡単な方法の1つは、配列を使用することです。これで、配列内で同じデータ型の要素がメモリの連続ブロックに格納されることがわかりました。したがって、この事実を利用して、私は次のことを思いつきました。
#include <iostream>
using namespace std;
int main()
{
int arr[2];
int* ptr = &arr[0];
int* ptr1 = &arr[1];
cout <<(size_t)ptr1-(size_t)ptr;
}
お役に立てれば。
これらの答えの多くは、構造がどのようになるかを知っていることを前提としています。このインタビューの質問は、既成概念にとらわれずに考えるように求めることを目的としていると思います。私は答えを探していましたが、ここで気に入った解決策は見つかりませんでした。私は言ってより良い仮定をします
struct foo {
int a;
banana b;
char c;
...
};
Foo [2]を作成することにより、メモリ内に2つの連続したfooオブジェクトが作成されます。そう...
foo[2] buffer = new foo[2];
foo a = buffer[0];
foo b = buffer[1];
return (&b-&a);
私のポインタ演算が正しく行われたと仮定すると、これはチケットであるはずです-そしてそのポータブルです!残念ながら、パディング、コンパイラ設定などもすべて役割を果たすでしょう。
考え?
これをあなたのコードに入れてください
次に、リンカー出力(マップファイル)を確認します
unsigned int uint_nabil;
unsigned long ulong_nabil;
あなたはこのようなものを手に入れるでしょう;
uint_nabil 700089a8 00000004
ulong_nabil 700089ac 00000004
サイズは4です!!