Zig: Call to C alignof gives different result than gcc/clang.

Created on 3 Aug 2020  路  5Comments  路  Source: ziglang/zig

#include <stdio.h>
#include <stddef.h>
#include <stdalign.h>

int main() {
    size_t val = alignof(max_align_t);
    printf("Val from C: %zu\n", val);

    return 0;
}

If I compile this code with gcc/clang and launch it, program prints Val from C: 16.
Now if I do:

build.zig

const Builder = @import("std").build.Builder;

pub fn build(b: *Builder) void {
    const mode = b.standardReleaseOptions();

    const exe = b.addExecutable("test-app", "src/main.zig");
    exe.linkLibC();
    exe.addSystemIncludeDir("./src/c_include");
    exe.setTarget(target);
    exe.setBuildMode(mode);
    exe.install();

    const run_cmd = exe.run();
    run_cmd.step.dependOn(b.getInstallStep());

    const run_step = b.step("run", "Run the app");
    run_step.dependOn(&run_cmd.step);
}

src/c_include/c_header.h

#include <stdio.h>
#include <stddef.h>
#include <stdalign.h>

size_t alignof_max_align_t() {
    size_t val = alignof(max_align_t);
    printf("Val from C: %zu\n", val);

    return val;
}

src/main.zig

const std = @import("std");
const c = @cImport(@cInclude("c_header.h"));

pub fn main() !void {
    const stdout = std.io.getStdOut().writer();
    const val = c.alignof_max_align_t();
    try stdout.print("Val from Zig: {}\n", .{val});
}

Then compile it and launch, the program prints:

Val from C: 32
Val from Zig: 32

Why?

bug translate-c

Most helpful comment

I ran zig translate-c main.c --library c > translated-c.zig where main.c is the first C code block from my issue.
The output is really long, but here is main function:

pub export fn main() c_int { 
    var val: usize = @sizeOf(max_align_t);
    _ = printf("Val from C: %zu\n", val);
    return 0;
}

Could the fact that it uses @sizeOf instead of @alignOf be the reason?

All 5 comments

Version: 0.6.0+6123201f0

I suspect this might be related to vector alignment. max_align_t is defined to have the max alignment of any scalar type, which may (confusingly) include SIMD intrinsics. Which means that if the compiler has AVX instructions enabled, this will be 32, otherwise it will be 16. If you compile the C version with -march=native, does it print 32?

No, it doesn't.

$ gcc -Wall -Wextra -pedantic -march=native main.c
$ ./a.out
Val from C: 16
$ rm a.out
$ clang -Wall -Wextra -pedantic -march=native main.c
$ ./a.out
Val from C: 16

I ran zig translate-c main.c --library c > translated-c.zig where main.c is the first C code block from my issue.
The output is really long, but here is main function:

pub export fn main() c_int { 
    var val: usize = @sizeOf(max_align_t);
    _ = printf("Val from C: %zu\n", val);
    return 0;
}

Could the fact that it uses @sizeOf instead of @alignOf be the reason?

#include <stdio.h>
#include <stddef.h>
#include <stdalign.h>

int main() {
    size_t val = sizeof(max_align_t);
    printf("Val from C: %zu\n", val);

    return 0;
}

Compiling this with GCC and running indeed prints 32.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

S0urc3C0de picture S0urc3C0de  路  3Comments

andrewrk picture andrewrk  路  3Comments

komuw picture komuw  路  3Comments

andersfr picture andersfr  路  3Comments

andrewrk picture andrewrk  路  3Comments