pebble/devsite/source/_guides/debugging/common-syntax-errors.md

190 lines
6 KiB
Markdown
Raw Permalink Normal View History

---
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
title: Common Syntax Errors
description: |
Details of common problems encountered when writing C apps for Pebble, and how
to resolve them.
guide_group: debugging
order: 2
---
If a developer is relatively new to writing Pebble apps (or new to the C
language in general), there may be times when problems with an app's code will
cause compilation errors. Some types of errors with the code itself can be
detected by the compiler and this helps reduce the number that cause problems
when the code is run on Pebble.
These are problems with how app code is written, as opposed to runtime errors
(discussed in {% guide_link debugging/common-runtime-errors %}), which may
include breaking the rules of the C language or bad practices that the compiler
is able to detect and show as an error. The following are some examples.
### Undeclared Variables
This error means that a variable that has been referenced is not available in
the current scope.
```nc|text
../src/main.c: In function 'toggle_logging':
../src/main.c:33:6: error: 'is_now_logging' undeclared (first use in this function)
if(is_now_logging == true) {
^
```
In the above example, the symbol `is_now_logging` has been used in the
`toggle_logging` function, but it was not first declared there. This could be
because the declaring line has been deleted, or it was expected to be available
globally, but isn't.
To fix this, consider where else the symbol is required. If it is needed in
other functions, move the declaration to a global scope (outside any function).
If it is needed only for this function, declare it before the offending line
(here line `33`).
### Undeclared Functions
Another variant of the above problem can occur when declaring new functions in a
code file. Due to the nature of C compilation, any function a
developer attempts to call must have been previously encountered by the compiler
in order to be visible. This can be done through
[forward declaration](http://en.wikipedia.org/wiki/Forward_declaration).
For example, the code segment below will not compile:
```c
static void window_load(Window *window) {
my_function();
}
void my_function() {
// Some code here
}
```
The compiler will report this with an 'implicit declaration' error, as the app
has implied the function's existence by calling it, even though the compiler has
not seen it previously:
```nc|text
../src/function-visibility.c: In function 'window_load':
../src/function-visibility.c:6:3: error: implicit declaration of function 'my_function' [-Werror=implicit-function-declaration]
my_function();
^
```
This is because the *declaration* of `my_function()` occurs after it is called
in `window_load()`. There are two options to fix this.
* Move the function declaration above any calls to it, so it has been
encountered by the compiler:
```c
void my_function() {
// Some code here
}
static void window_load(Window *window) {
my_function();
}
```
* Declare the function by prototype before it is called, and provide the
implementation later:
```c
void my_function();
static void window_load(Window *window) {
my_function();
}
void my_function() {
// Some code here
}
```
### Too Few Arguments
When creating functions with argument lists, sometimes the requirements of the
function change and the developer forgets to update the places where it is
called.
```nc|text
../src/main.c: In function 'select_click_handler':
../src/main.c:57:3: error: too few arguments to function 'toggle_logging'
toggle_logging();
^
../src/main.c:32:13: note: declared here
static void toggle_logging(bool will_log) {
^
```
The example above reports that the app tried to call the `toggle_logging()`
function in `select_click_handler()` on line 57, but did not supply enough
arguments. The argument list expected in the function definition is shown in the
second part of the output message, which here exists on line 32 and expects an
extra value of type `bool`.
To fix this, establish which version of the function is required, and update
either the calls or the declaration to match.
### Incorrect Callback Implementations
In the Pebble SDK there are many instances where the developer must implement a
function signature required for callbacks, such as for a ``WindowHandlers``
object. This means that when implementing the handler the developer-defined
callback must match the return type and argument list specified in the API
documentation.
For example, the ``WindowHandler`` callback (used for the `load` and `unload`
events in a ``Window``'s lifecycle) has the following signature:
```c
typedef void(* WindowHandler)(struct Window *window)
```
This specifies a return type of `void` and a single argument: a pointer of type
``Window``. Therefore the implemented callback should look like this:
```c
void window_load(Window *window) {
}
```
If the developer does not specify the correct return type and argument list in
their callback implementation, the compiler will let them know with an error
like the following, stating that the type of function passed by the developer
does not match that which is expected:
```nc|text
../src/main.c: In function 'init':
../src/main.c:82:5: error: initialization from incompatible pointer type [-Werror]
.load = main_window_load,
^
../src/main.c:82:5: error: (near initialization for '(anonymous).load') [-Werror]
```
To fix this, double check that the implementation provided has the same return
type and argument list as specified in the API documentation.