|
Technically C, since the latter will give the C++ compiler indigestion due to lack of const qualifier.
There's just not an option for that language here at CP.
That said, these should be syntactically valid, compilable, and comparable functionality-wise.
To err is human. Fortune favors the monsters.
|
|
|
|
|
|
C - equivalent is storage size but not value.
sz is an address with no storage associated with it. it's value is unknown.
sx is an address with a null value.
wrote some code to confirm
"A little time, a little trouble, your better day"
Badfinger
|
|
|
|
|
which compiler? I use GCC and malloc(0) gives me null back (presumably the error condition in this case, like with out of mem)
To err is human. Fortune favors the monsters.
|
|
|
|
|
It would actually depend on your libc implementation, not the compiler. Using RedHat Rawhide, I get the following:
[k5054@localhost tmp]$ cat example.c
#include <stdio.h>
#include <stdlib.h>
int main()
{
char *s = malloc(0);
printf("s = %p\n", s);
free(s);
return 0;
}
[k5054@localhost tmp]$ gcc --version
gcc (GCC) 12.2.1 20221121 (Red Hat 12.2.1-4)
Copyright (C) 2022 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
[k5054@localhost tmp]$ gcc -Wall -Wextra example.c -o example
[k5054@localhost tmp]$ ./example
s = 0x182f2a0
[k5054@localhost tmp]$ Maybe if you're cross compiling for your controller du jour, its libc is doing that?
Keep Calm and Carry On
|
|
|
|
|
Yeah, I am on a different platform.
To err is human. Fortune favors the monsters.
|
|
|
|
|
I use same and get the same result.
"A little time, a little trouble, your better day"
Badfinger
|
|
|
|
|
Don't try malloc(0) at home!
C-2018 7.22.3 states, among other things: If the size of the space requested is zero, the behavior is implementation-defined: either a null pointer is returned to indicate an error, or the behavior is as if the size were some nonzero value, except that the returned pointer shall not be used to access an object.
IOW this is non-portable code, and should be avoided.
Freedom is the freedom to say that two plus two make four. If that is granted, all else follows.
-- 6079 Smith W.
|
|
|
|
|
int ZERO = 0;
char *sz = (char*)malloc(ZERO);
char *sx = strchr("",1);
printf("Hello world!\n");
printf( "Sizeof char_sz %d bytes value %p\n", (int)sizeof(sz), sz );
printf( "Sizeof char_sx %d bytes value %p\n", (int)sizeof(sx), sx );
Hello world!
Sizeof char_sz 8 bytes value 0000000000ba13f0
Sizeof char_sx 8 bytes value 0000000000000000
Note: value for sz seems to be random which implies it's an address in memory with a value of whatever is in memory at the time. Value of sx is consistently zero or null string.
"A little time, a little trouble, your better day"
Badfinger
|
|
|
|
|
The result of malloc(0) is implementation defined. Your compiler apparently allocates a minimal block of memory for each malloc(0), allowing you to call free() on the block. Note that the block may not be portably dereferenced, as its size is 0.
The other option in the C Standard is to return NULL. This also allows free() to be called on the "block", because free(NULL) is specifically allowed in the Standard. The result also cannot be dereferenced (dereferencing NULL is undefined behaviour).
Freedom is the freedom to say that two plus two make four. If that is granted, all else follows.
-- 6079 Smith W.
|
|
|
|
|
I agree. One last test. Using calloc and malloc
I tried both malloc and calloc and got same results.
The calls do not return NULL even if specifying ZERO bytes.
I am using Codeblocks IDE with latest GCC and have C std-17 2017 standard flag set
int ZERO = 0;
char *sz;
char *sx;
printf("Hello world!\n");
sz = (char*)malloc(ZERO);
// sz = (char*)calloc(ZERO, (int)sizeof(sz));
if( sz == NULL ) printf( "returned NULL allocated zero bytes\n");
else printf( "NULL not returned from malloc, allocated 8 bytes\n" );
sx = strchr("",1);
printf( "Sizeof char_sz %d bytes value %p\n", (int)sizeof(sz), sz );
printf( "Sizeof char_sx %d bytes value %p\n", (int)sizeof(sx), sx );
free( sz );
printf( "Sizeof char_sz %d bytes value %p after free\n", (int)sizeof(sz), sz );
Results:
Hello world!
NULL not returned from malloc, allocated 8 bytes
Sizeof char_sz 8 bytes value 0000000000b213f0
Sizeof char_sx 8 bytes value 0000000000000000
Sizeof char_sz 8 bytes value 0000000000b213f0 after free
"A little time, a little trouble, your better day"
Badfinger
|
|
|
|
|
Again.
GCC is behaving according to the C Standard, which specifies that malloc(0) or calloc(0, x) return either NULL, or a unique pointer. This is implementation defined behaviour - the implementation must specify what behaviour it supports.
Your code is not checking the size of the block referenced by sz, sizeof(*sz). It is checking the size of the pointer, sizeof(sz). You are apparently running on a system with 64-bit pointers.
If malloc(x) or calloc(y, x) return a non-NULL pointer, you are guaranteed that it points to a memory area of at least x or x * y chars, respectively. In order to discover the exact area, you will need to call an implementation-specific API; the C Standard does not define an API to return the actual size of an allocated memory area.
Note that even if the result of malloc(0) or calloc(0, x) is a unique pointer, that pointer cannot be portably dereferenced, as it is guaranteed to reference only a zero-sized memory area.
Freedom is the freedom to say that two plus two make four. If that is granted, all else follows.
-- 6079 Smith W.
|
|
|
|
|
Understood.
My point is asking for zero bytes of memory gets me an OK (not a NULL) whether I use calloc or malloc.
I have problems with that behavior.
I realize that it's saying I got what I wanted.
Checking for NULL is not a guaranteed successful approach.
Instead one should be checking for non-zero allocation parameters prior to calling malloc or calloc!
"A little time, a little trouble, your better day"
Badfinger
|
|
|
|
|
Testing to see what actually happens is a good idea.
But never forget: "Implementation dependent" does not mean "The way gcc implements it" (or any other given compiler), even though gcc users often seems to think that way. Any other C compiler may think differently.
|
|
|
|
|
I agree.
"A little time, a little trouble, your better day"
Badfinger
|
|
|
|
|
The testing showed me that using calloc and malloc requires some extra checking for zero memory requests.
As a result, I am scanning my uses of it in my older code. I do not think I inadvertently allocated zero memory, I want to be sure. BTW malloc and calloc return NULL when memory requested is less than zero.
"A little time, a little trouble, your better day"
Badfinger
|
|
|
|
|
Behavior for the first one is implementation defined[^].
Meanwhile, the second is just a weird way of saying null.
Am I missing something?
Mircea
|
|
|
|
|
agree,
GNU GCC
BTW can you id the background in my photo. Hint Canada
"A little time, a little trouble, your better day"
Badfinger
modified 13-Dec-22 1:11am.
|
|
|
|
|
jmaida wrote: GNU GCC
Not quite. malloc() is provided by libc. For most linux distributions, that will be provided by GNU libc, but it doesn't have to be.
Keep Calm and Carry On
|
|
|
|
|
jmaida wrote: BTW can you id the background in my photo. Hint Canada
Not really: you are too big and skyline is too small. Looks like "city by the water" but that's not narrowing it much
Mircea
|
|
|
|
|
Behind is Detriot River and Canada @ Angstrom Park, part of Amherstburg, just north of Crystal Island.
"A little time, a little trouble, your better day"
Badfinger
|
|
|
|
|
mwh, standards shmandereds. They both return null.
To err is human. Fortune favors the monsters.
|
|
|
|
|
char* sz = (char*)(strchr("1",'0' + 1) - strchr("1",'0' + 1));
Now ask some C++ guru, how to make this constexpr .
|
|
|
|
|
I'm wondering if it is a subversive campaign to create a SoapBox?
I’ve given up trying to be calm. However, I am open to feeling slightly less agitated.
|
|
|
|
|
Or are you just thin-skinned at _this_ moment?
|
|
|
|