El Lenguaje PocketC
El lenguaje es muy similar al C standard en su sintaxis, pero tiene un
conjunto de características diferentes. Lo más notable, no
hay structs ni typedefs, y faltan algunos operadores, como la coma y el
operador condicional (?:). Se agregó un tipo de datos string y los
valores son en cierta forma poco estrictos en su tipificación. La
siguiente sección es para aquellos que ya tienen una cierta familiaridad
con C. También está disponible una guía
completa para aquellos que no conocen C.
Guía resumida del lenguaje PocketC
Tipos de datos
Hay cinco tipos de datos en PocketC: enteros de 32-bit con signo (int),
números de coma flotante de 32-bit (float), caracteres
de 8-bit con signo (char), cadenas terminadas en nulo (string),
punteros (pointer), y matrices unidimensionales.
Expresiones
Una expresión está compuesta por variables, llamadas funciones
y constates de cualquier tipo unidas por operadores y paréntesis.
Así, las siguientes expresiones son válidas:
3 + 5
6.7 + 23
"Hello " + "World"
5*3 + calcular()
Cuando una expresión contiene valores de diferente tipo, los valores
son primero convertidos al mismo tipo y después se aplica el operador.
Por ejemplo en la siguiente expresión:
5.7 + 8
El 8 es primero convertido a float (8.0), y entonces se suman los dos
números (5.7 + 8.0). Esto se vuelve un poco más interesante
cuando usamos strings. Por ejemplo:
"El resultado es " + (5 + 8)
5 es primero sumado a 8, dando como resultado 13. El 13 es entonces
convertido a string, y agregado a "El resultado es " resultando "El resultado
es 13". Sin embargo,
"El resultado es " + 5 + 8
resultará en "El resultado es 58", porque primero se convierte
el 5 a string y entonces se suma a "El resultado es "...
Por supuesto es posible la tipificación explícita:
56 + (int)"7"
es evaluado como 63.
Se pueden usar los siguientes operadores (en orden de precedencia (la
menor primero), con asociatividad):
Operador |
Asoc. |
Descripción |
= |
derecha |
asigna el valor de la expresión de la derecha a la variable
de la izquierda |
|| |
izquierda |
operador lógico ‘or’, devuelve 0 si falso, 1 si verdadero |
&& |
izquierda |
operador lógico ‘and’ |
| |
izquierda |
'or' por bits |
^ |
izquierda |
'xor' por bits |
& |
izquierda |
'and' por bits |
== != < <= > >= |
izquierda |
operadores relacionales |
<< >> |
izquierda |
operadores de rotación de bits. Los operandos deben ser char
o int. |
+ - |
izquierda |
Suma y resta |
* / % |
izquierda |
multiplicación, división y módulo |
- ! ++ -- ~ *
[] () & @[] |
izquierda |
operadores unitarios, derreferencia de punteros, operador de dirección,
llamadas de función (para punteros a funciones), subíndices
de matrices (para pointers), y operador de acceso a caracteres ( @[] ej.
string str = "bob"; str@[0] = 'B'; ) |
Nota: No se ejecutan atajos lógicos en los operandos de
|| y &&
Nota2: La asignación compuestas de operadores (+=, -=,
*=, etc.) no es soportada.
Nota3: La coma y el operador condicional (?:) no están
soportados.
Variables
-
Los tipos de variables son: int, float, char, string, pointer y matrices
unidimensionales.
-
Las variables locales deben declararse antes de cualquier código
en las funciones.
-
Es mejor crear matrices grandes en forma global que local.
-
Se pueden usar inicializadores de variables (desde la versión 3.5).
Las expresiones de inicialización deben ser constantes y del tipo
correcto. También está disponible la inicialización
de matrices (Ej. string days[7] = { "Dom", "Lun" };). Si no se especifican
todos los elementos de la matriz los elementos finales se asignan por defecto
(0 or ""). (Ej. int x[3] = {1, 2}; // x[2] == 0)
-
Todas las variables, globales y locales, se inicializan a cero o cadena
vacía.
-
Los nombres de variables pueden tener hasta 31 caracteres, y son sensibles
a mayúsculas y minúsculas.
Punteros
Un puntero se define con el tipo pointer, no con int*,
por ejemplo. Importante, los punteros en PocketC no tiene tipo. En su lugar,
toman el tipo del dato que apuntan. Adicionalmente, un puntero puede referir
a una función, y en ese caso se usa así:
func(int x) { return 5*x; }
main() {
pointer ptr;
int result;
ptr = func;
result = (*ptr)(7);
puts("5*7=" + result);
}
Los valores de los punteros no corresponde a direcciones de memoria de
PalmOS.
Acceso a caracteres de cadenas
Para obtener o cambiar un carácter individual dentro de una variable
string, usar stringVariable@[indice]. El índice del
primer carácter es 0. Se producirá un error en tiempo de
ejecución si se intenta acceder a una posición posterior
al final de la cadena. Ejemplo:
string str = "bob";
...
puts(str@[1]); // Imprime la segunda letra de
str@[1] = 'X'; // Cambia str de "bob" a "bXb"
Nota: esta función no puede usarse con punteros, tampoco
se puede obtener la dirección de la cadena resultante. En otras
palabras, ;as siguientes expresiones son inválidas: &str@[i],
*pstr@[i], (*pstr)@[i]
Instrucciones
Las siguientes instrucciones tienen soporte total: for, while, do,
break, continue, if, then, return, switch, case, default. Con las
instrucciones switch se pueden usar strings.
Nota: for requiere una expresión de condición
(ej. for (;;) es incorrecto, en su lugar usar for (;true;)
o while (true)) . Además el operador coma no está
soportado.
Funciones
-
Las funciones se declaran sin tipificar su resultado. Debido a esta falta
de tipo es posible devolver cualquier tipo de resultado, incluso múltiples
tipos. El tipo devuelto es el correspondiente a la expresión de
la instrucción return. Si no se especifica valor de resultado la
función devuelve 0 entero.
-
La variables locales deben declararse antes de cualquier otra instrucción
de código.
-
Debe existir una función main que no tiene parámetros.
-
Las funciones no pueden tomar matrices como parámetros. Pueden,
sin embargo, tener punteros como argumentos, logrando de esta forma la
misma funcionalidad.
-
Una función no puede ser invocada antes de su definición.
-
Se pueden usar prototipos de las funciones (desde la versión 3.02).
-
Se puede efectuar recursividad.
Include
-
Se pueden usar sólo tres niveles de includes (ej. si memo A tiene
include B, el cual tiene include C, y este a su vez tiene include D, D
no puede tener ningún include)
-
No agregar '//' al nombre del archivo en la instrucción include.
-
El archivo mencionado en include puede comenzar con '/$' en lugar de '//'
para que no se vea en el formulario de compilación.
-
El archivo include puede ser tipo doc. Nota: PocketC buscará el
memo correspondiente antes de buscar entre los archivos doc.
-
En PocketC Desktop Edition, todos los \ en la ruta deben anteponerse con
el carácter de escape.
Ejemplo:
// Mi applet largo
include "Parte1"
include "Parte2"
main() {
// llamadas a las funciones definidas en otros memos
}
Nota: include sólo puede ser usado en el nivel global
(ej. no se puede usar include dentro de funciones)
Librerías
-
Emplear la palabra clave library para usar librerías nativas.
-
NO USAR esta palabra clave con MathLib. Las funciones de MathLib están
disponibles como funciones propietarias.
Ejemplo:
// Mi Applet
library "PocketCLib"
main() {
int x;
// llamadas a funciones definidas en la librería nativa
x = times5(7); // donde times5(int) está definida en "PocketCLib"
}
Caracteres especiales
Hay dos formas de agregar caracteres especiales a una cadena. La primera
es agregándola por número, como en:
str = "Este es un cuadrado: " + (char)149;
El otro método es a través de secuencias de escape. Son válidas
las siguientes secuencias:
Secuencia de escape |
\\ |
\' |
\" |
\n |
\t |
\x |
Interpretación |
\ |
' |
" |
nueva línea |
tabulación |
carácter especificado por los siguientes dígitos hexadecimales.
Ejemplo: '\x95' es el carácter block (decimal 149) |
Preprocesador
Están contempladas las siguientes directivas del preprocesador:
#define, #undef, #ifdef, #ifndef, #else, #endif. Las macros no pueden tomar
parámetros. Las siguientes constantes están predefinidas:
__PKTC__,
__PKTC_PALM__, y si PocketC Desktop Edition está compilando
un archivo .prc, __PKTC_PRC__.