<div dir="ltr">'\0' is a single character, not a string. Note the use of signal quote marks, THIS IS IMPORTANT. It is an 8bit value equivalent to the byte 0x00, or an integer 0x00000000. You could replace '\0' with 0x00 everywhere in your code and they would be exactly the same.<div><br></div><div>"" is a string containing one byte, '\0'. It's equivalent to a byte array like { 0x00 }. This array is allocate somewhere in memory, not a literal value in your program like the previous example.</div><div><br></div><div>When you say "const char *" that's a C-ism for saying you want an array of bytes. An array in C is passed by the address of the first element. This is why clang (correctly) throws a warning.</div><div><br></div><div>In your first case, clang sees you have a literal 0x00 when a pointer value is expected. But it says "Hey, I can take that literal 0x00 and cast it to a pointer value!" It throws a warning because this isn't usually a good thing to do, but in this case it is equivalent to NULL so it kind of works. For example, if you had used a literal 'A', then clang would pass in the pointer value 0x41, which would try to access whatever memory is at address 0x00000041, which is almost certainly crash.</div><div><br></div><div>In your second case, clang sees you have an array of one byte (it doesn't care about the arrays contents), and passes the address of the first element of the array. This array is allocated in the global data section of your program. Let's pretend the address of that first element is 0xDEADBEEF.</div><div><br></div><div>Can you see the difference? In the first case clang has to cast character (or integer) to a char*, which is usually dangerous. In the second case it is given the proper type (a memory address) that the function argument says it wants.</div><div><br></div><div>It's would really worry me that the upstream developers of this package don't understand the difference.</div></div><div class="gmail_extra"><br><div class="gmail_quote">On Tue, Jun 21, 2016 at 1:21 AM, Mojca Miklavec <span dir="ltr"><<a href="mailto:mojca@macports.org" target="_blank">mojca@macports.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hi,<br>
<br>
When I tried porting some software (originally written for Windows and<br>
now asking for C++14) to MacPorts I was stuck with an external piece<br>
of a code written in C, compiled with C++ (I don't fully understand<br>
why it is compiled with C++, but I cannot change that).<br>
<br>
This is a minimal example that fails:<br>
<br>
void test(const char *a) {}<br>
int main()<br>
{<br>
test('\0'); // pass an empty string<br>
return 0;<br>
}<br>
<br>
<br>
A relatively recent clang++ compiler just throws a warning (using libstdc++):<br>
<br>
> clang++-mp-3.7 test-dev.c<br>
clang: warning: treating 'c' input as 'c++' when in C++ mode, this<br>
behavior is deprecated<br>
test-dev.c:5:10: warning: expression which evaluates to zero treated<br>
as a null pointer constant of type 'const char *'<br>
[-Wnon-literal-null-conversion]<br>
test('\0');<br>
^~~~<br>
1 warning generated.<br>
<br>
<br>
But the same compiler in C++11 or C++14 mode throws an error:<br>
<br>
> clang++-mp-3.7 -stdlib=libc++ -std=c++14 test-dev.c<br>
clang: warning: treating 'c' input as 'c++' when in C++ mode, this<br>
behavior is deprecated<br>
test-dev.c:5:5: error: no matching function for call to 'test'<br>
test('\0');<br>
^~~~<br>
test-dev.c:1:6: note: candidate function not viable: no known<br>
conversion from 'char' to 'const char *' for 1st argument<br>
void test(const char *a) {}<br>
^<br>
1 error generated.<br>
<br>
<br>
GCC doesn't seem to care though:<br>
<br>
> g++-mp-4.9 -std=c++14 test-dev.c<br>
> # no warnings or errors<br>
<br>
<br>
I didn't test on Windows. I installed clang 3.5 on Linux (the latest<br>
version shipped by Debian-based Mint) and the results were the same as<br>
on Mac:<br>
<br>
> clang++-3.5 -std=c++11 tes-dev.c<br>
clang: warning: treating 'c' input as 'c++' when in C++ mode, this<br>
behavior is deprecated<br>
test-dev.c:4:5: error: no matching function for call to 'test'<br>
test('\0');<br>
^~~~<br>
test-dev.c:1:6: note: candidate function not viable: no known<br>
conversion from 'char' to 'const char *' for 1st argument<br>
void test(const char *a) {}<br>
^<br>
1 error generated.<br>
<br>
> clang++-3.5 test-dev.c<br>
clang: warning: treating 'c' input as 'c++' when in C++ mode, this<br>
behavior is deprecated<br>
test-dev.c:4:10: warning: expression which evaluates to zero treated<br>
as a null pointer constant of type 'const char *'<br>
[-Wnon-literal-null-conversion]<br>
test('\0');<br>
^~~~<br>
1 warning generated.<br>
<br>
I came up with a workaround, defining<br>
<br>
const char *empty = "";<br>
test(empty);<br>
<br>
<br>
The upstream developers replied:<br>
<br>
first:<br>
> If I'm understanding correctly, it also seems like a bug in the C++<br>
> compiler to think that a character constant is not const,<br>
<br>
second:<br>
> If I understand the patch well, the C code supplies a character \0<br>
> when an empty string is expected. In K&R C it is the same but strictly<br>
> checking in C++ they are different things.<br>
<br>
<br>
So I was wondering which compiler was right: g++ or clang++?<br>
<br>
Mojca<br>
_______________________________________________<br>
macports-dev mailing list<br>
<a href="mailto:macports-dev@lists.macosforge.org">macports-dev@lists.macosforge.org</a><br>
<a href="https://lists.macosforge.org/mailman/listinfo/macports-dev" rel="noreferrer" target="_blank">https://lists.macosforge.org/mailman/listinfo/macports-dev</a><br>
</blockquote></div><br></div>