web-dev-qa-db-ja.com

sizeofを使用しないデータ型のサイズ

Xなどのデータ型があり、その型の変数またはポインターを宣言せずに、もちろんsizeof演算子を使用せずに、そのサイズを知りたいです。

これは可能ですか?データ型のサイズと範囲を含む標準のヘッダーファイルを使用することを考えましたが、ユーザー定義のデータ型では機能しません。

19
sud03r

私の考えでは、これは「++、+ =、または+を使用せずに2つのintを追加するにはどうすればよいですか?」というカテゴリに当てはまります。それは時間の無駄です。このようなことをすることで、未定義の振る舞いのモンスターを避けようとすることができます。

size_t size = (size_t)(1 + ((X*)0));

declareXへの型またはポインタの変数ではないことに注意してください。

43
CB Bailey

ほら、sizeofisこのための言語機能。唯一のものなので、これを達成するための唯一のポータブルな方法です。

いくつかの特別なケースでは、特定のオブジェクトのサイズを理解するために他のヒューリスティックを使用する移植性のないコードを生成できます[*](おそらくオブジェクトが自分のサイズを追跡するようにすることによって)が、すべての簿記を自分で行う必要があります。

[*] OOPの意味ではなく、非常に一般的な意味のオブジェクト。

12
dmckee

ええと、私はアマチュアです。しかし、私はこの問題を試し、sizeofを使用せずに正しい答えを得ました。これがお役に立てば幸いです。私は整数のサイズを見つけようとしています。

int *a,*s, v=10;

a=&v;

s=a;

a++;

int intsize=(int)a-(int)s;

printf("%d",intsize);
10
bubblegum

このインタビューの質問に対する正解は、「sizeof()が私のためにそれを行うのに、なぜそれをしたいのか、そしてそれを行う唯一の移植可能な方法なのか?」です。

5
Chris K

パディングの可能性は、それを導入するために使用されるルールの知識がなければ、すべての希望を防ぎます。そして、それらは実装に依存します。

4
AProgrammer

これを試して:

int a;
printf("%u\n", (int)(&a+1)-(int)(&a));
3
Majid

特定のプロセッサの [〜#〜] abi [〜#〜] を読んで、パズルを解くことができます。これは、構造がメモリ内にどのように配置されているかを説明しています。プロセッサごとに異なる可能性があります。しかし、コンパイラーを作成しているのでない限り、この問題を解決するための1つの正しい方法であるsizeofだけを使用したくないのは驚くべきことです。

3
Norman Ramsey

xがデータ型の場合:

#define SIZEOF(X) (unsigned int)( (X *)0+1 )

xが変数の場合:

#define SIZEOF(X) (unsigned int)( (char *)(&X+1)-(char *)(&X) )
2
ramshankar

コンパイラのソースを調べます。あなたが得るでしょう:

  • 標準データ型のサイズ。
  • 構造体のパディングのルール

そしてこれから、何でも予想されるサイズ。

少なくとも変数にスペースを割り当て、それにセンチネル値を入力できれば、少しずつ変更して値が変更されるかどうかを確認できますが、それでもパディングに関する情報はわかりません。

2
Stefano Borini

これを試して:

 #include<stdio.h>

int main(){

  int *ptr = 0;

  ptr++;
  printf("Size of int:  %d",ptr);

  return 0;
1
Sateesh

ユーザーコードでC89ソリューション以降で利用可能:

  1. タイプXの変数を宣言しません。
  2. タイプXへのポインタを宣言しません。
  3. 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以降が必要です。

1
chux

これがコードです。トリックは、ポインタオブジェクトを作成し、そのアドレスを保存し、ポインタをインクリメントしてから、前のアドレスから新しいアドレスを減算することです。重要な点は、ポインタがインクリメントされるとき、実際にはそれが指しているオブジェクトに等しいサイズで移動することです。したがって、ここではクラスのサイズ(それが指しているオブジェクト)です。

#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);
}

よろしく

0
swati kunte

これを行う簡単な方法の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;
}

お役に立てれば。

0
Rohan Shahane

これらの答えの多くは、構造がどのようになるかを知っていることを前提としています。このインタビューの質問は、既成概念にとらわれずに考えるように求めることを目的としていると思います。私は答えを探していましたが、ここで気に入った解決策は見つかりませんでした。私は言ってより良い仮定をします

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);

私のポインタ演算が正しく行われたと仮定すると、これはチケットであるはずです-そしてそのポータブルです!残念ながら、パディング、コンパイラ設定などもすべて役割を果たすでしょう。

考え?

0
mohbandy

これをあなたのコードに入れてください

次に、リンカー出力(マップファイル)を確認します

unsigned int  uint_nabil;
unsigned long  ulong_nabil;

あなたはこのようなものを手に入れるでしょう;

uint_nabil 700089a8 00000004
ulong_nabil 700089ac    00000004

サイズは4です!!

0
Smartfusion