2010-05-05 4 views
8

Cela peut sembler étrange, mais en C (size_t) (void *) 0 == 0 n'est pas garanti par la spécification du langage. Les compilateurs peuvent utiliser n'importe quelle valeur pour null (bien qu'ils utilisent presque toujours 0.)Y at-il une différence entre null et 0 lors de l'affectation à des pointeurs dans un code dangereux?

En C#, vous pouvez assigner null ou (T *) 0 à un pointeur dans un code non sécurisé.

  1. Y a-t-il une différence?
  2. (long) (void *) 0 == 0 (garanti ou non d'autres termes: IntPtr.Zero.ToInt64() == 0)

MSDN a ceci à dire au sujet de IntPtr. Zéro:

"La valeur de ce champ n'est pas équivalente à null." Eh bien, si vous voulez être compatible avec le code C, cela a beaucoup de sens - cela ne servirait à rien si l'interopérabilité n'était pas convertie en un pointeur C null. Mais je veux savoir si IntPtr.Zero.ToInt64() == 0 qui peut être possible, même si IntPtr.Zero interne est une autre valeur (le CLR peut ou ne peut pas convertir null à 0 dans l'opération de distribution)

Pas un doublon de this question

Répondre

5

pourrait éviter le problème:

char* foo = (char*)(void*)0; 
char* bar = default(char*); // <======= the one to look at 
Console.WriteLine(foo == bar); // writes True 

ils sont les mêmes, mais en utilisant default évite d'avoir à intégrer une hypothèse ou moulages désagréables dans le code. Démontage ce qui précède, la seule différence est signé/non signé - commencent tous deux par une constante de 4 octets (i4/u4) puis jeté à int natif (i/u) (les // commentaires sont les miens):

.maxstack 2 
.locals init (
    [0] char* foo, 
    [1] char* bar) 
L_0000: ldc.i4.0 // (char*)(void*)0; 
L_0001: conv.i 
L_0002: stloc.0 // foo= 
L_0003: ldc.i4.0 // default(char*); 
L_0004: conv.u 
L_0005: stloc.1 // bar= 
L_0006: ldloc.0 
L_0007: ldloc.1 
L_0008: ceq // foo == bar 
L_000a: call void [mscorlib]System.Console::WriteLine(bool) 
+0

Ah oui, j'ai oublié que par défaut fonctionne sur les pointeurs. C'est une bonne solution. – Eloff

0

En C, NULL est défini comme spécifique à l'architecture. Alors que la plupart des architectures utilisent 0, d'autres non. Donc, vous ne pouvez pas supposer que NULL == 0 en C.

Pas tout à fait sûr de savoir comment cela fonctionne en C# mais je recommande de vous en tenir à la façon standard de spécifier NULL en C# au lieu de le jeter à 0. Vous

+0

Quelle est la manière standard de spécifier null pour les pointeurs en C#? J'ai vu les deux utilisés, et le casting 0 semble être plus commun. J'aime null parce que c'est plus lisible, mais la décision sur laquelle utiliser dépend vraiment de la réponse à savoir si oui ou non ils sont équivalents. – Eloff

Questions connexes