将变量设为const还是最终保存字节或内存?

时间:2017-06-02 04:05:42

标签: c variables constants final

我一直在使用某个程序而且我一直在尝试节省字节和存储空间。

我的C程序中有很多变量,但我想知道是否可以通过在整个程序class ServerThread implements Runnable { @Override public void run() { try { mServerSocket = new ServerSocket(0); setLocalPort(mServerSocket.getLocalPort()); while (!Thread.currentThread().isInterrupted()) { Log.d(TAG, "ServerSocket Created, awaiting connection"); setSocket(mServerSocket.accept()); //line of error Log.d(TAG, "Connected."); Toast.makeText(context, "Connected", Toast.LENGTH_SHORT).show(); if (mChatClient == null) { int port = mSocket.getPort(); InetAddress address = mSocket.getInetAddress(); connectToServer(address, port); } } } catch (IOException e) { Log.e(TAG, "Error creating ServerSocket: ", e); e.printStackTrace(); } } } 或{{1}中创建don't change的一些变量来减少程序的大小。 }}

所以我的问题是这些:

  • 将静态变量标识为06-02 06:07:43.804 26779-26779/com.example.android.nsdchat E/MultiWindowProxy: getServiceInstance failed! 06-02 06:07:43.829 26779-26786/com.example.android.nsdchat E/art: Failed sending reply to debugger: Broken pipe 06-02 06:07:45.117 26779-26794/com.example.android.nsdchat E/ONS: 1. NsdChat (_http._tcp. -- 0 -- 0) 06-02 06:07:47.132 26779-26796/com.example.android.nsdchat E/Surface: getSlotFromBufferLocked: unknown buffer: 0x7f9de01110 06-02 06:07:56.925 26779-26779/com.example.android.nsdchat E/IAE: listener in use 06-02 06:07:59.331 26779-26779/com.example.android.nsdchat E/IAE: listener in use 06-02 06:08:04.004 26779-26794/com.example.android.nsdchat E/NsdHelper: Resolve Succeeded. name: NsdChat, type: ._http._tcp, host: /192.168.82.103, port: 48308 06-02 06:08:05.995 26779-26796/com.example.android.nsdchat E/Surface: getSlotFromBufferLocked: unknown buffer: 0x7f9da665c0 06-02 06:08:07.364 26779-26796/com.example.android.nsdchat E/Surface: getSlotFromBufferLocked: unknown buffer: 0x7f9da6c990 06-02 06:08:07.716 26779-26793/com.example.android.nsdchat E/ChatConnection: Error creating ServerSocket: java.net.SocketException: Socket closed at libcore.io.Posix.accept(Native Method) at libcore.io.BlockGuardOs.accept(BlockGuardOs.java:63) at java.net.PlainSocketImpl.accept(PlainSocketImpl.java:94) at java.net.ServerSocket.implAccept(ServerSocket.java:217) at java.net.ServerSocket.accept(ServerSocket.java:141) at com.example.android.nsdchat.ChatConnection$ChatServer$ServerThread.run(ChatConnection.java:153) at java.lang.Thread.run(Thread.java:818) 06-02 06:08:07.997 26779-26796/com.example.android.nsdchat E/Surface: getSlotFromBufferLocked: unknown buffer: 0x7f9dcd2bd0 时是否存在任何字节保存?
  • 如果通过这样做保存了字节,为什么要保存它们?如果变量是const,程序如何以不同方式存储变量,为什么这种方式需要更少的存储空间呢?
  • 如果通过将变量定义为final来保存字节,那么为什么开发人员首先会以这种方式定义变量?我们是否可以省略constant,以防我们以后需要更改变量(特别是如果这样做没有垮台)?
  • 是否只有一些IDE /语言可以使用constant变量保存字节?

感谢您的帮助,非常感谢。

4 个答案:

答案 0 :(得分:5)

我认为你正在研究深度嵌入式系统(如cortex-M处理器)。 对于这些,您知道SRAM是一种稀缺资源,而您有足够的FLASH存储器。 然后尽可能多地使用 const 关键字来表示任何不会改变的变量。 这样做会告诉编译器将变量存储在FLASH存储器中,而不是存储在SRAM中。

例如,要在系统上存储文本,您可以执行以下操作:

const char* const txtMenuRoot[] = { "Hello, this is the root menu", "Another text" };

然后不仅文本存储在FLASH中,还存储在指针中。

答案 1 :(得分:3)

您的所有问题都很大程度上取决于编译器和环境。用于嵌入式环境的C编译器可以在保存内存方面做得很好,而有些则可能没有。

  

将静态变量识别为常量时是否存在任何字节保存?

是的,有可能。但请注意," const"通常不打算指定如何存储变量 - 而是它的意思是帮助程序员和编译器更好地理解源代码(当编译器和#34;理解得更好",它可以产生更好的目标代码)。某些编译器可以使用该信息将变量存储在只读存储器中,或者将其删除并将其转换为目标代码中的文字。但在您的问题中,可能#define更合适。

  

如果通过这样做保存了字节,为什么要保存它们?如果变量是常量,程序如何以不同方式存储变量,为什么这种方式需要更少的存储空间?

源代码中声明的变量可以在目标代码中的不同位置,以及在目标文件加载到内存中并执行时的不同位置。请注意,同样,各种体系结构存在差异 - 例如,在小型8/16位MCU(电子设备的CPU)中,通常没有" loading"一个目标文件。所以变量的值存储在某个地方 - 无论如何。但是在低级别,编译器可以使用文字而不是地址,这大多节省了一些内存。假设您在源代码中声明了一个常量变量GAIN = 5。当在某个公式中使用该变量时,编译器会发出类似" LD R12,GAIN" (将寄存器R12加载到地址GAIN的内容,其中存储了变量GAIN)。但编译器也可以发出" LD R12,#5" (在R12中加载值" 5")。在这两种情况下都需要一条指令,但在第二种情况下,没有涉及变量的存储器。这是一种保存,也可以更快。

  

如果通过将变量定义为常量来保存字节,那么为什么开发人员首先会以这种方式定义变量?我们是否可以省略const以防万一我们以后需要更改变量(特别是如果这样做没有垮台)?

如前所述," const"关键字旨在更好地定义将对变量执行的操作。为清楚起见,这对程序员很有用。明确说明变量不打算被修改是有用的,特别是当变量是形式参数时。在某些环境中,实际上只有一些只能读取而不能写入的只读存储器,如果变量(可能是一个系统变量")被标记为" const"程序员和编译器都清楚,如果它遇到试图修改该变量的代码,它可以发出警告。

  

是否只有一些IDE /语言用常量变量保存字节?

肯定是的。但是,不要谈论IDE:他们只是编辑。关于语言,事情很复杂:它完全取决于实现和优化。可能这种保存仅用于编译器(而不是解释器),并且很大程度上取决于编译器的优化选项/功能。

答案 2 :(得分:2)

以这种方式考虑const(C中没有finalconstant这样的东西,所以我会忽略它。如果编译器可以节省内存,那么(特别是在编译优化大小时)。 const为编译器提供有关对象属性的更多信息。编译器可以在有更多信息时做出更明智的决策,并且不会阻止编译器做出与拥有该信息之前完全相同的决策。

它不会伤害并且可能有所帮助,它还有助于使用代码的程序员更容易理解它。编译器和程序员都得到了帮助,没有人受伤。这是一个双赢的局面。

答案 3 :(得分:0)

编译器可以根据代码知识减少使用的内存,const帮助编译器知道真实的代码行为(如果激活警告,你可以建议将const放在何处)。

但是由于所使用的hw的对齐限制,结构可以包含未使用的字节,并且编译器不能改变结构的内部顺序。这只能在更改代码时完成。

struct wide               struct compact
{                         {
    int_least32_t i1;             int_least32_t i1,
    int_least8_t b;                             i2;
    int_least32_t i2;             int_least8_t b;
}                         }

由于对齐限制,struct wide在成员'b'和'i2'之间可以有一个空的空格。 结构紧凑中不是这种情况,因为元素从最宽的列出,可能需要更大的对齐,到较小的。

在相同的情况下,struct compact甚至可以提供更快的代码。