locale.h
locale.h controls how your program formats and interprets culture-specific data: whether the decimal separator is . or ,, what the currency symbol is, which characters count as letters. By default a C program runs in the "C" locale — ASCII, . decimal separator, no localisation — which is predictable but not what a German or French user expects to see.
#include <locale.h> setlocale(LC_ALL, ""); // pick up the user's environment locale setlocale(LC_ALL, "C"); // reset to the predictable ASCII baseline setlocale(LC_NUMERIC, "de_DE.UTF-8"); // German number format only
The category lets you change one aspect without touching the others:
| Category | Controls |
LC_ALL | Everything |
LC_NUMERIC | Decimal point, thousands separator |
LC_MONETARY | Currency symbol and format |
LC_CTYPE | isalpha, toupper etc. |
LC_COLLATE | String comparison order |
LC_TIME | strftime output |
localeconv() returns a struct lconv with all the current locale's formatting strings: decimal_point, thousands_sep, currency_symbol, and more.
The practical rule: call setlocale(LC_ALL, "") at startup if you are producing output for humans. But be careful with LC_NUMERIC — any library that calls setlocale on your behalf can change the decimal separator under your feet, which will break strtod parsing of machine-generated data. Keep LC_NUMERIC as "C" when parsing programmatic input.
Practice
// compile: gcc -o localedemo localedemo.c // run: ./localedemo // description: show how locale changes decimal formatting; install de_DE if missing #include <locale.h> #include <stdio.h> int main(void) { double pi = 3.141592653589793; setlocale(LC_ALL, "C"); printf("C locale: %f\n", pi); // 3.141593 if (!setlocale(LC_NUMERIC, "de_DE.UTF-8") && !setlocale(LC_NUMERIC, "de_DE")) puts("de_DE locale not available; install with: sudo locale-gen de_DE.UTF-8"); else { printf("de_DE locale: %f\n", pi); // 3,141593 (comma!) printf("decimal_point = '%s'\n", localeconv()->decimal_point); } return 0; }
If the German locale is installed you will see a comma instead of a dot in the second line. If not, install it with sudo locale-gen de_DE.UTF-8 on Debian/Ubuntu. Once you have seen this in action it is hard to forget that LC_NUMERIC can silently change how printf and strtod work.
