Question
I have a long SQLite query stored in a C string literal:
const char *sql_query = "SELECT statuses.word_id FROM lang1_words, statuses WHERE statuses.word_id = lang1_words.word_id ORDER BY lang1_words.word ASC";
How can I format this query across multiple source-code lines so it is easier to read? Writing one quoted string across physical lines produces a compiler error:
const char *sql_query = "SELECT word_id
FROM table1, table2
WHERE table2.word_id = table1.word_id
ORDER BY table1.word ASC";
Is there a correct way to write a C or Objective-C SQL query over multiple lines?
Short Answer
You will learn why ordinary C string literals cannot contain an unescaped source-code newline, and how adjacent string literals are automatically combined by the compiler. This lets you format long SQL statements cleanly without changing the resulting query.
Concept
A C string literal starts and ends with double quotes. A physical newline in the source file ends the current source line, so it cannot appear directly inside a normal quoted string literal.
C provides a convenient solution: adjacent string literals are concatenated automatically at compile time. Put each readable part in its own quoted literal, with no comma or + between them.
const char *sql_query =
"SELECT statuses.word_id "
"FROM lang1_words, statuses "
"WHERE statuses.word_id = lang1_words.word_id "
"ORDER BY lang1_words.word ASC";
The compiler treats this exactly like one string literal:
"SELECT statuses.word_id FROM lang1_words, statuses WHERE statuses.word_id = lang1_words.word_id ORDER BY lang1_words.word ASC"
This matters because long strings occur often in real programs: SQL queries, error messages, URLs, JSON fragments, regular expressions, and command-line templates. Compile-time concatenation keeps source code readable while avoiding runtime string-building work.
In Objective-C, the same rule works for NSString literals. Use the @ prefix on every adjacent literal:
NSString *query =
@"SELECT word_id "
@"FROM table1, table2 "
@"WHERE table2.word_id = table1.word_id";
Mental Model
Think of each quoted literal as a piece of paper placed side by side before your program is built. The C compiler tapes adjacent pieces together into one continuous string.
"SELECT " "name " "FROM users"
becomes:
SELECT name FROM users
The compiler does not automatically add spaces, newlines, or indentation while joining the pieces. You must include any characters that should exist in the final string.
Syntax and Examples
Use adjacent quoted literals with whitespace included deliberately at the end or beginning of each fragment.
const char *sql_query =
"SELECT word_id "
"FROM table1, table2 "
"WHERE table2.word_id = table1.word_id "
"ORDER BY table1.word ASC";
The final value is:
SELECT word_id FROM table1, table2 WHERE table2.word_id = table1.word_id ORDER BY table1.word ASC
Notice the trailing spaces after word_id, table2, and table1.word_id. They are necessary so SQL keywords do not run together.
Including actual newline characters
SQL normally accepts whitespace such as spaces and newlines. If you want the string itself to contain newline characters, use \n:
const char *sql_query =
"SELECT word_id\n"
"FROM table1, table2\n"
"WHERE table2.word_id = table1.word_id\n"
"ORDER BY table1.word ASC";
This produces a multi-line string at runtime. The \n is one newline character in the resulting string.
Objective-C NSString
NSString *query =
@"SELECT word_id "
@"FROM table1 "
@"WHERE word_id > 0";
For an NSString, each adjacent literal must use @.
Step by Step Execution
Consider this C code:
const char *query =
"SELECT id "
"FROM users "
"WHERE active = 1";
- The compiler reads the first literal:
"SELECT id ". - It sees another string literal immediately next to it:
"FROM users ". - It concatenates those two literals.
- It then appends
"WHERE active = 1". - The variable receives a pointer to one complete null-terminated C string.
The effective result is:
const char *query = "SELECT id FROM users WHERE active = 1";
No runtime concatenation function is called. The joining happens while compiling.
If you instead use newlines explicitly:
const char *query =
"SELECT id\n"
"FROM users\n"
"WHERE active = 1";
then the runtime value contains line breaks between SQL clauses.
Real World Use Cases
- SQLite queries: Format
SELECT,FROM,WHERE, andORDER BYclauses on separate source lines. - Prepared statements: Keep a long parameterized query readable while binding values separately.
- Error messages: Build readable static messages without runtime allocation.
- HTTP headers: Store a fixed request template with
\r\nline endings. - Command templates: Define a long, constant command or URL in logical pieces.
- Objective-C app code: Create a readable
NSStringused with database APIs or network requests.
For SQL specifically, use placeholders and bind values rather than inserting user input into the query text.
Real Codebase Usage
In production C and Objective-C code, long constant queries are usually written as adjacent literals aligned by SQL clause:
static const char *find_user_sql =
"SELECT id, display_name, email "
"FROM users "
"WHERE email = ? "
"AND deleted_at IS NULL "
"LIMIT 1";
Common practices include:
- Use prepared statements: Keep
?placeholders in SQL and bind values with the database API. - Make constant queries
static const: Limit visibility to the current source file when appropriate. - Keep whitespace visible: Usually place one trailing space at the end of each fragment, or use
\nconsistently. - Split at clause boundaries:
SELECT,FROM,JOIN,WHERE,GROUP BY, andORDER BYmake natural break points. - Avoid dynamic SQL where possible: A fixed query plus bound parameters is safer and easier to test.
Example with SQLite preparation:
static const char *sql =
"SELECT word_id "
"FROM table1 "
"WHERE word = ?";
sqlite3_stmt *statement = NULL;
int result = sqlite3_prepare_v2(db, sql, -1, &statement, NULL);
The formatting of sql has no negative effect on sqlite3_prepare_v2; it receives one complete string.
Common Mistakes
Forgetting spaces between fragments
Adjacent literals do not receive an automatic separator.
/* Wrong: becomes "SELECT idFROM users" */
const char *query =
"SELECT id"
"FROM users";
Add a space where SQL requires one:
const char *query =
"SELECT id "
"FROM users";
Placing an actual source newline inside a literal
/* Invalid C */
const char *query = "SELECT id
FROM users";
Use adjacent literals, or use \n if a newline must be part of the resulting value.
Using + as though C strings were JavaScript strings
/* Wrong in C: these are pointers/arrays, not concatenated strings */
const char *query = "SELECT id " + "FROM users";
Use adjacent literals for compile-time constants:
const char *query = "SELECT id " "FROM users";
Mixing C and Objective-C literal forms
/* Do not mix these when constructing an NSString literal expression. */
NSString *query = @"SELECT id " "FROM users";
Use @ for every Objective-C literal:
NSString *query = @"SELECT id " @"FROM users";
Treating formatting as SQL injection protection
Line splitting only improves readability. It does not make user-provided data safe. Use parameter binding for values.
Comparisons
| Technique | Resulting string contains newlines? | When to use it |
|---|---|---|
| Adjacent literals | No, unless you add them | Readable source code for a long constant string |
\n escape sequence | Yes | The receiving API or output should see line breaks |
Source line continuation with \ | Usually no | Avoid for long strings; it is harder to read and easier to break |
Runtime concatenation (snprintf, builders) | Depends | Some parts are only known while the program runs |
C string versus Objective-C string
| Language form | Type commonly used | Example |
|---|---|---|
| C string literal | const char * | "SELECT " "id" |
| Objective-C string literal | NSString * | @"SELECT " @"id" |
Adjacent literal concatenation is for literals known in source code. If you need to combine variable data, use an appropriate runtime API—but do not assemble SQL values with string formatting when parameter binding is available.
Cheat Sheet
/* C: compiler joins adjacent literals */
const char *text =
"first part "
"second part";
/* Result: "first part second part" */
/* Objective-C: prefix every literal with @ */
NSString *text =
@"first part "
@"second part";
/* Put real newlines in the runtime string */
const char *text =
"first line\n"
"second line";
Rules:
- Adjacent literals need no
+, comma, or function call. - The compiler adds nothing between fragments.
- Include spaces yourself when words or SQL clauses need separation.
- A raw newline inside a normal string literal is invalid.
- Use
\nfor a newline character in the final string. - Use SQL placeholders and parameter binding for values from users or external input.
FAQ
Can a C string literal span multiple source lines?
Not as one ordinary quoted literal with a raw newline inside it. Use adjacent string literals, or write \n when the final string needs a newline character.
Does C automatically insert a space between adjacent string literals?
No. "one" "two" becomes "onetwo". Add a space to either fragment when needed.
Are adjacent C string literals concatenated at runtime?
No. The compiler concatenates them, so there is no runtime string-joining cost for literal fragments.
Can I use this syntax with SQLite SQL?
Yes. SQLite receives one complete query string. Spaces or \n characters between SQL tokens keep the query valid and readable.
Should I use \n or trailing spaces for multi-line SQL source code?
Either can work. Trailing spaces create a single-line runtime query; \n creates a formatted runtime query. Choose the form that is clearest for your logging and debugging needs.
Does Objective-C support adjacent string literals?
Yes. Use adjacent @"..." literals to create an NSString.
Can I concatenate a variable with a string literal this way?
No. Adjacent literal concatenation works only for literals. For SQL values, use prepared-statement parameters rather than concatenating variables into SQL text.
Mini Project
Description
Create a readable SQLite query constant for listing active products. The task demonstrates how adjacent C string literals make SQL easier to maintain while preserving required SQL whitespace.
Goal
Write one valid C string containing a formatted multi-clause SQL query without placing a raw newline inside any string literal.
Requirements
Use const char * for the query.
Split the query into at least four adjacent string literals.
Include SELECT, FROM, WHERE, and ORDER BY clauses.
Ensure SQL keywords and identifiers are separated by whitespace.
Use a ? placeholder for a minimum price value.
Keep learning
Related questions
2D Array Loop Order and Cache Performance in C
Learn why swapping nested loops changes 2D array performance in C, using row-major memory layout, cache locality, and practical benchmarks.
Array-to-Pointer Conversion in C and C++ Explained
Learn what array-to-pointer conversion means in C and C++, how array decay works, and how it differs from a pointer to an array.
Building More Fault-Tolerant Embedded C++ Applications for Radiation-Prone ARM Systems
Learn practical C++ and compile-time techniques to reduce soft-error damage in embedded ARM systems exposed to radiation.