-
-
Notifications
You must be signed in to change notification settings - Fork 2.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add c_char type #875
Comments
Usinge C's void test_func(signed char c);
int main(void) {
test_func(-1);
} and void test_func(unsigned char c) {
// should print a value between 0 and 255
printf("%u\n", (unsigned int)c);
} The expected output is However, if I compile them with clang into an executable, with optimizations ( This is probably due to I think that this is what is happening: That means that, declaring |
void test_func_signed(signed char c);
void test_func_unsigned(unsigned char c);
pub extern fn test_func_signed(c: i8) void;
pub extern fn test_func_unsigned(c: u8) void; Zig correctly understands |
void test_func(char c); produces
|
To better show how zig is involved in this issue, lets consider this example.
extern void test_func(char c);
#include <stdio.h>
#include "test.h"
void test_func(char c) {
// should print a value between -128 and 127
printf("%i\n", (int)(signed char)c);
}
The output is |
If you are faced with a .h file which has the function prototype: void print_char(char c); Given that The difference between zig choosing Therefore |
From the C language spec:
Zig is an implementation of a subset of the C language. In the Zig implementation of C, Every implementation must make a choice one way or the other. Zig baked its choice into the semantics of the C-to-Zig interface and guarantees that it will not change without a major version bump. The indeterminate signedness of |
If you look at my example, I am explicitly casting
Shouldn't Zig's implementation be compatible with the system's C (at least in terms of ABI compatibility)? This does not mean that |
Yes, that is correct. I need to go back and look at your examples more closely and think about the ABI more carefully. Thanks for taking the time to make sure I understood your point, I appreciate it. To clarify, Zig guarantees compatibility with the C ABI of the chosen target, which includes a C environment, for example you can choose MSVC or GNU as your "C environment". |
Char and uint_8 are not identical, because char pointers are exempt from strict aliasing while uint_8 pointers are not. |
As mentioned in #3999 (comment), some platforms have |
C's ctest.c:6:24: warning: pointer targets in initialization of 'const uint8_t *' {aka 'const unsigned char *'} from 'char *' differ in signedness [-Wpointer-sign]
6 | const uint8_t *t = "H";
| ^~~
ctest.c:7:23: warning: pointer targets in initialization of 'const int8_t *' {aka 'const signed char *'} from 'char *' differ in signedness [-Wpointer-sign]
7 | const int8_t *v = "H";
| ^~~ |
|
Yes, the sign of char can be introspected with macros: #ifdef IS_SIGNED
#error "IS_SIGNED already defined"
#else
#define IS_SIGNED(Type) (((Type)-1) < 0)
#endif For more context, read also this issue: marler8997/ziglibc#1 which ziglibc must eventually decide on how to handle it internally wrt c compatibility guarantees. |
Most of the time, Sorry for the nitpick, but strict aliasing rules are just finicky : ) |
See #861.
This will be identical to a
u8
internally except generated header files will result in achar
type instead of auint8_t
type.We should be able to cast between the two types transparently.
You should never see
c_char
unless you have to generate achar
type for a c header.The text was updated successfully, but these errors were encountered: