web-dev-qa-db-fra.com

taille d'un type de données sans utiliser sizeof

J'ai un type de données, disons X, et je veux connaître sa taille sans déclarer une variable ou un pointeur de ce type et bien sûr sans utiliser l'opérateur sizeof.

Est-ce possible? J'ai pensé utiliser des fichiers d'en-tête standard qui contiennent la taille et la plage de types de données mais cela ne fonctionne pas avec le type de données défini par l'utilisateur.

19
sud03r

À mon avis, cela entre dans la catégorie "comment ajouter deux unités sans utiliser ++, + = ou +?". C'est une perte de temps. Vous pouvez essayer d'éviter les monstres de comportement indéfini en faisant quelque chose comme ceci.

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

Notez que je déclare une variable de type ou un pointeur sur X.

43
CB Bailey

Regardez, sizeof est la facilité linguistique pour cela. Le seul, c'est donc le seul moyen portable pour y parvenir.

Dans certains cas particuliers, vous pourriez générer du code non portable utilisant une autre heuristique pour comprendre la taille d'objets particuliers [*] (probablement en leur faisant garder leur propre taille), mais il vous faudrait faire toute la comptabilité vous-même. .

[*] Objets dans un sens très général plutôt que OOP.

12
dmckee

Bien, je suis un amateur..mais j'ai essayé ce problème et j'ai eu la bonne réponse sans utiliser sizeof. J'espère que cela aide .. J'essaie de trouver la taille d'un entier.

int *a,*s, v=10;

a=&v;

s=a;

a++;

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

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

La réponse correcte à cette question de l’entrevue est "Pourquoi voudrais-je faire cela, quand sizeof () le fait pour moi, et qu’il s’agit de la seule méthode portable pour le faire?"

5
Chris K

La possibilité de rembourrage empêche tout espoir sans la connaissance des règles utilisées pour son introduction. Et ceux-ci dépendent de la mise en œuvre.

4
AProgrammer

Essaye ça:

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

Vous pouvez le résoudre en lisant le ABI de votre processeur, ce qui explique comment les structures sont mises en mémoire. C'est potentiellement différent pour chaque processeur. Mais à moins d'écrire un compilateur, il est étonnant que vous ne souhaitiez pas simplement utiliser sizeof, qui est le seul moyen de résoudre ce problème.

3
Norman Ramsey

si X est le type de données:

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

si X est une variable:

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

Regardez dans les sources du compilateur. Tu auras :

  • la taille des types de données standard.
  • les règles de remplissage des structures

et de là, la taille attendue de rien.

Si vous pouviez au moins allouer de l'espace à la variable et y insérer une valeur sentinelle, vous pouvez la changer petit à petit et voir si la valeur change, mais cela ne vous dira toujours aucune information sur le remplissage.

2
Stefano Borini

Essaye ça:

 #include<stdio.h>

int main(){

  int *ptr = 0;

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

  return 0;
1
Sateesh

Disponible depuis la solution C89 qui en code utilisateur:

  1. Ne déclare pas une variable de type X.
  2. Ne déclare pas un pointeur pour taper X.
  3. Sans utiliser l'opérateur sizeof.

Assez facile à faire en utilisant le code standard suggéré par @steve jessop

offsetof(type, member-designator)

qui se développe en une expression constante entière de type size_t, dont la valeur est le décalage en octets, vers le membre de structure ..., à partir du début de sa structure ... C11 §7.19 3

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

Remarque: Ce code utilise "%zu" qui nécessite C99 à partir de maintenant.

1
chux

Voici le code: L'astuce consiste à créer un objet pointeur, à enregistrer son adresse, à l'incrémenter puis à soustraire la nouvelle adresse de la précédente. Le point clé est que lorsqu'un pointeur est incrémenté, il se déplace réellement d'une taille égale à l'objet qu'il pointe, donc ici, la taille de la classe (dont l'objet est pointé).

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

Cordialement

0
swati kunte

Une méthode simple consiste à utiliser des tableaux. Nous savons maintenant que dans des tableaux, des éléments du même type de données sont stockés dans un bloc de mémoire contigu. Donc, en exploitant ce fait, je suis arrivé à suivre:

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

J'espère que cela t'aides.

0
Rohan Shahane

Beaucoup de ces réponses supposent que vous sachiez à quoi ressemblera votre structure. Je crois que cette question d'entrevue a pour but de vous demander de sortir des sentiers battus. Je cherchais la réponse, mais je n'ai trouvé aucune solution qui me plaise ici. Je vais faire une meilleure hypothèse en disant

struct foo {
  int a;
  banana b;
  char c;
  ...
};

En créant foo [2], je vais maintenant avoir 2 objets foo consécutifs en mémoire. Alors...

foo[2] buffer = new foo[2];
foo a = buffer[0];
foo b = buffer[1];

return (&b-&a);

En supposant que mon arithmétique de pointeur soit correcte, ceci devrait être le ticket - et son portable! Malheureusement, des choses comme le rembourrage, les réglages du compilateur, etc. joueraient également un rôle

Pensées?

0
mohbandy

mettez ceci à votre code

puis vérifiez la sortie de l'éditeur de liens (fichier map)

unsigned int  uint_nabil;
unsigned long  ulong_nabil;

vous obtiendrez quelque chose comme ça;

uint_nabil 700089a8 00000004
ulong_nabil 700089ac    00000004

4 est la taille !!

0
Smartfusion