What Using AI for Go Taught Me About C Code Generation

What Using AI for Go Taught Me About C Code Generation

I've been using AI to write code since GitHub Copilot launched in 2022. Over the past year, I've spent hours every day working with Claude Code, Cursor, GitHub Copilot, and most recently Cursor CLI. I've built tools that automate git commits, switched entire projects from manual coding to AI-assisted development, and generally become one of those developers who reaches for AI before reaching for documentation.

The results in Go have been genuinely impressive. AI handles error handling boilerplate brilliantly, generates comprehensive test suites in seconds, and can scaffold entire microservices that actually compile. My workflow has completely transformed - I'm far more productive, and the code quality is often better than what I'd write manually because AI is more disciplined about following patterns.

So naturally, I got curious: would this translate to C?

The short answer is no. The long answer reveals something important about both AI's current limitations and the fundamental differences between modern systems languages.

The Go Experience: When AI Actually Works

Before diving into where things break down, it's worth understanding what "working well" looks like. In Go, AI code generation feels almost magical for certain tasks.

Need error handling for a new function? AI wraps everything correctly, checks all the edge cases, and returns errors properly formatted. Building a new API endpoint? It scaffolds the handler, adds proper validation, and even includes sensible middleware. Writing mocks for testing? AI generates them faster than you can explain what you need.

This isn't just about speed. The code quality is consistently high because Go's design - with its explicit error handling, clear syntax, and strong conventions - gives AI clear patterns to follow. There's usually one obvious way to do things, and AI has seen that pattern thousands of times in its training data.

The garbage collector handles memory management, so AI never has to think about allocation and deallocation. Concurrency is explicit through goroutines and channels, giving AI clear primitives to work with. The standard library is comprehensive but small, so AI actually knows it well.

Most importantly, when AI makes mistakes in Go, they're usually obvious. The code won't compile, or the error will be clear. There's not much undefined behaviour lurking beneath the surface.

First Contact: Trying AI Code Generation for C

I decided to test this properly. I took a systems programming task I know well - building a simple HTTP server that handles concurrent connections - and asked various AI tools to implement it in C.

The results were... educational.

Every tool confidently generated code that looked plausible at first glance. Professional-looking functions, reasonable structure, comments explaining the logic. But as I started actually reviewing the code, problems emerged.

The first version used strcpy() without any bounds checking. Just casually copying user input into fixed-size buffers. Any security-conscious C programmer would immediately spot this, but AI treated it as the natural choice - probably because it's shorter to type and appears constantly in older codebases.

When I pointed this out, the AI switched to strncpy() - but got the usage wrong. It didn't null-terminate the string in the edge case where the source is longer than the buffer. This is exactly the kind of subtle bug that makes C infamous, and AI walked straight into it.

The memory management was similarly problematic. The code called malloc() but only freed memory on success paths. Error paths just returned early, leaking memory. There were no checks for malloc() returning NULL. Dynamic allocations where static would've been safer and simpler.

But here's what really concerned me: the code compiled and would probably run. It would seem to work in testing with benign inputs. The problems would only emerge under stress, with malicious inputs, or after extended runtime. This is exactly the kind of code that creates security vulnerabilities and production incidents.

Why C Is Different: The Memory Management Problem

The core issue isn't that AI is bad at C specifically. It's that C's essential complexity cannot be abstracted away, and AI's probabilistic approach to code generation collides badly with C's unforgiving nature.

In Go, if you make a memory mistake, the garbage collector catches it. You might have a memory leak if you hold references unnecessarily, but you won't have undefined behaviour. There's no such thing as a use-after-free bug in Go. Buffer overflows are impossible with slices.

In C, memory is your responsibility. Every allocation needs a corresponding deallocation. Every buffer needs bounds checking. Every pointer needs validation. And if you get any of this wrong, you don't get a nice error message - you get undefined behaviour.

Undefined behaviour is the killer. The C specification defines numerous constructs that invoke it: dereferencing null pointers, out-of-bounds array access, use of uninitialized variables, signed integer overflow, and many more. When you trigger undefined behaviour, the compiler is free to do literally anything. Your program might crash immediately, might corrupt data silently, might appear to work fine in testing and fail catastrophically in production.

AI models don't reason about undefined behaviour. They pattern-match based on what they've seen in training data. If most examples in the training data use strcpy() because it's shorter and simpler to demonstrate, AI will use strcpy(). If many examples don't check malloc() returns because that clutters the "essential" logic being demonstrated, AI won't check either.

The problem compounds because AI has seen far more Python and JavaScript code than C code in recent years. The patterns it knows best come from languages with memory safety built in. When it generates C, it's often applying high-level language patterns to a low-level language - and that's exactly when dangerous bugs emerge.

The 70% Problem Becomes the 40% Problem

There's a concept that's emerged around AI code generation called the "70% problem." AI gets you about 70% of the way to working code, then you spend time debugging and refining the last 30%. For many developers, this is still a net win - 70% is better than starting from scratch.

But in C, that ratio flips dramatically. Based on my testing, AI code generation for C gets you maybe 40% of the way there. And worse, that remaining 60% isn't just polish and refinement - it's fundamental corrections to memory management, buffer handling, and error checking.

The review burden is crushing. You need to check every single allocation, every string operation, every pointer dereference. You're essentially doing a security audit on code that looks superficially correct but is riddled with subtle bugs.

This is particularly problematic because it plays to AI's greatest weakness: making code that seems right but isn't. As one developer put it: "Would you rather write some code, or constantly code-review verbose, sneakily wrong junior-level code?"

With Go, AI-generated code that compiles usually works. With C, code that compiles and runs in testing might still be catastrophically wrong. The compile-run cycle gives you false confidence.

Security Implications: Why This Matters

Here's where this gets serious. Memory safety issues account for 60-70% of security vulnerabilities in major software. Buffer overflows, use-after-free, null pointer dereferences - these aren't theoretical problems. They're the attack vectors for real exploits.

The US government recently mandated that federal agencies develop memory safety roadmaps by January 2026. Major tech companies are rewriting critical infrastructure in memory-safe languages. This is a multi-billion dollar problem affecting critical systems worldwide.

And now we're potentially introducing tools that will confidently generate memory-unsafe C code for developers who might not have the experience to spot every issue.

I'm not saying AI should never be used for C programming. But the review process needs to be rigorous. You need to assume every AI-generated C function has security issues until proven otherwise. You need static analysis tools, fuzzing, and careful manual review.

This is very different from Go, where AI-generated code tends to be memory-safe by default because the language enforces it. The risks are fundamentally different.

Embedded Systems: Where AI Really Struggles

The problems multiply when you move to embedded C programming. I tested AI generation for microcontroller code, and the results were even worse.

AI doesn't understand resource constraints. It generates code that works fine on a desktop with gigabytes of RAM but fails spectacularly on a microcontroller with 64KB. It suggests dynamic memory allocation when you need static allocation only. It produces recursive solutions for problems where you have limited stack space.

Real-time constraints? AI doesn't consider them. It generates code that might take an unpredictable amount of time to execute, which is fatal in hard real-time systems. It doesn't account for interrupt contexts, doesn't understand volatile variables properly, and has no concept of deterministic execution.

One AI tool confidently suggested using printf() for debugging output on a microcontroller - but printf() is enormous, pulls in most of the standard library, and can easily bloat your binary beyond available flash memory. An experienced embedded developer would use a minimal debug output function, but AI reaches for familiar patterns.

The platform fragmentation makes this worse. C code is highly compiler and hardware dependent. AI assumes a generic environment, suggesting GCC-specific extensions when you're targeting a different compiler, ignoring endianness issues, assuming 64-bit when you need 16-bit or 32-bit code.

For embedded systems, AI code generation for C currently adds more problems than it solves. The review burden is simply too high, and the errors too fundamental.

Where AI Actually Helps with C

This isn't entirely doom and gloom. There are legitimate use cases where AI assists with C development effectively:

Documentation and explanation. AI is excellent at explaining what existing C code does, documenting complex functions, and generating comments. This is genuinely useful for maintaining legacy codebases.

Algorithm implementations. When you need a standard algorithm (sorting, searching, data structure operations), AI can provide a reasonable starting point—though you still need to verify it thoroughly and adapt it to your specific constraints.

Boilerplate generation. Things like error handling patterns, standard function templates, and repetitive struct definitions. AI can scaffold these quickly, though again with review.

Test case generation. AI can suggest test cases and edge cases you might not have considered. Not the test code itself necessarily, but the scenarios to test.

Code transformation. Converting between similar patterns, updating deprecated API usage, or refactoring for readability. These are often safer because you're working with existing code rather than generating new allocations and buffer operations.

The key pattern: AI works best when it's assisting human expertise, not replacing it. An experienced C programmer can use AI to speed up routine tasks while catching the dangerous suggestions immediately. But for someone learning C or without systems programming experience, AI code generation becomes actively dangerous.

Language Design Matters

This experiment taught me something important about language design and its interaction with AI tooling. The features that make Go easy for humans to reason about - garbage collection, memory safety, explicit error handling, limited but complete standard library - also make it easier for AI to generate correct code.

C's lack of these features isn't a bug, it's the point. C gives you direct control over memory and hardware because that control is necessary for systems programming. But that control comes with responsibility, and AI doesn't understand responsibility - it understands patterns.

The languages that work best with AI code generation seem to be those with strong safety guarantees and clear conventions. Go, Rust (with its borrow checker forcing correct patterns), TypeScript (with its type system catching errors). Languages where the compiler is your ally.

C is different. The C compiler assumes you know what you're doing. It will happily compile code that invokes undefined behaviour, that leaks memory, that contains buffer overflows. It trusts you to be careful. AI is not careful - it's confident.

The Future: AI for C vs AI for Modern Alternatives

Looking forward, I think we'll see two parallel trends. First, AI tooling for C will improve as models get better at reasoning about memory management and undefined behaviour. Specialised models trained specifically on safe C patterns, integrated with static analysis tools, could become genuinely helpful.

But second - and probably more significant - the push toward memory-safe languages will accelerate. When AI makes developing in Go and Rust dramatically more productive while making C development marginally more productive at best, the economic case for rewriting critical systems becomes stronger.

If I can build a systems-level application in Go with AI assistance in a fraction of the time it takes to carefully verify AI-generated C code, why would I choose C? The only remaining reasons are specific performance requirements, existing codebase constraints, or direct hardware interaction needs.

For new projects, especially those where security matters, choosing C becomes increasingly hard to justify. The combination of memory safety and AI assistance that languages like Go and Rust provide is simply more productive and more secure.

Practical Recommendations

If you're using AI for C programming, here's what I learned:

Assume every AI-generated C function has security vulnerabilities until proven otherwise. Don't trust that code compiles and runs in testing—assume it has memory safety issues and review accordingly.

Use static analysis tools aggressively. Run Valgrind, AddressSanitizer, and other tools on all AI-generated C code. Many issues that aren't obvious to human review will be caught by tooling.

Focus AI on safe use cases. Documentation, explanation, algorithm research, test case suggestions. Avoid using AI for anything involving memory management, buffer handling, or pointer arithmetic until you can verify every line.

Consider AI code generation as a reason to choose safer languages. If AI makes Go development dramatically more productive than C development, factor that into your language choice for new projects.

Invest in C expertise if you must use C with AI. The review burden requires deep understanding of memory management, undefined behaviour, and security implications. Junior developers should not rely on AI for C code generation.

Conclusion

Using AI for Go code generation has transformed my workflow. Using AI for C code generation taught me exactly why C is being phased out of critical systems.

The problem isn't that AI can't write C code - it obviously can generate syntactically correct C. The problem is that correct C requires a level of care and understanding of memory management that current AI models don't possess. The gap between "code that compiles" and "code that's safe" is enormous in C, and AI consistently produces code in that dangerous middle ground.

For modern systems programming, this reinforces my belief that memory-safe languages with AI assistance are the future. The combination of language-level safety guarantees and AI productivity tools is simply too powerful to ignore.

C isn't going away entirely - there will always be use cases where its control and performance are necessary. But for the vast majority of systems programming, the era of choosing C by default is ending. AI code generation is accelerating that transition, not because AI is bad at C, but because AI reveals exactly why C's lack of memory safety is such a problem.

If you're starting a new systems project today and AI assistance is part of your workflow, seriously consider whether C is the right choice. The productivity difference is stark, and the security implications are significant. Sometimes the best way to use AI for C programming is to use AI to write Go instead.


Need help with your business?

Enjoyed this post? I help companies navigate AI implementation, fintech architecture, and technical strategy. Whether you're scaling engineering teams or building AI-powered products, I'd love to discuss your challenges.

Learn more about how I can support you.

Get practical insights weekly

Real solutions to real problems. No fluff, just production-ready code and workflows that work.
You've successfully subscribed to Kyle Redelinghuys
Great! Next, complete checkout to get full access to all premium content.
Welcome back! You've successfully signed in.
Success! Your account is fully activated, you now have access to all content.
Error! Stripe checkout failed.
Success! Your billing info is updated.
Error! Billing info update failed.